指针自增移动字节数等于其所指类型的大小,而非指针自身大小;void 不支持算术运算,需转为 char 才能按字节偏移;跨数组或非法内存的指针算术是未定义行为。

int* 自增移动 4 字节,但不是“固定加 4”
移动字节数 = sizeof(int),不是硬编码的 4。虽然在绝大多数现代平台(x86/x64)上 sizeof(int) 是 4,但标准只规定 int 至少 16 位,实际大小由编译器和 ABI 决定。比如某些嵌入式平台或旧系统中 sizeof(int) 可能是 2;而 int* 在 64 位系统下仍可能指向 4 字节 int,偏移量不变。
关键点在于:指针算术完全依赖 *ptr 的类型,与指针变量自身大小(sizeof(int*) 通常是 4 或 8)无关。
char* 和 double* 自增移动字节数不同
char* 自增移动 1 字节,double* 通常移动 8 字节——因为 sizeof(char) == 1,sizeof(double) 通常是 8(IEEE 754 双精度)。这决定了它们遍历数组时的步长差异:
-
char str[] = "abc"; char* p = str; p++;→ 地址 +1,指向'b' -
double arr[2]; double* q = arr; q++;→ 地址 +sizeof(double),跳过整个第一个double单元
误用类型会导致越界或读错数据,比如用 int* 去遍历 char 数组,每次跳 4 字节,会漏掉中间 3 个元素。
void* 不能直接自增
C++ 明确禁止对 void* 做 ++、+ 等算术运算,编译器报错:error: invalid operands to binary expression ('void*' and 'int')。这是因为 void 是不完整类型,sizeof(void) 无定义,编译器无法计算步长。
若真需要按字节偏移,必须先转成 char*:
void* base = malloc(100); char* p = static_cast<char>(base); p += 5; // 合法:移动 5 字节 </char>
直接写 static_cast<int>(base) + 1</int> 虽然能编译,但语义危险——它假设 base 指向的是 int 序列,而原始内存未必满足该布局。
ptr + n 的偏移量是 n × sizeof(*ptr),不是 n × sizeof(ptr)
新手常混淆指针类型大小和所指类型大小。sizeof(int*) 是指针变量占的字节数(通常 4 或 8),而 ptr + n 的地址增量是 n * sizeof(int)(即 4 × n)。例如:
int arr[3] = {0};
int* p = arr;
printf("%p\n", (void*)(p + 1)); // 输出比 &arr[0] 高 4 字节
printf("%zu\n", sizeof(p)); // 输出 8(在 64 位平台)
真正影响偏移的是 *p 类型,不是 p 类型。这也是为什么 int* 和 long* 在同一平台下自增移动字节数可能不同——如果 sizeof(long) != sizeof(int)(如 LP64 模型下 long 是 8 字节)。
最易被忽略的一点:指针算术只对指向同一数组(或末尾一格)的指针有效;跨数组、悬空指针、或非数组内存上做 ++ 属于未定义行为,编译器不保证诊断,运行时可能静默出错。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











