C语言指针运算结果不符合预期的运行原理解析
C语言指针运算原理说明
核心规则
C语言中指针的加减运算步长由指针指向的类型大小决定:T*类型的指针执行+1操作时,实际偏移的字节数等于sizeof(T),而非偏移1字节。
逐行代码运行解析
我们假设int占4字节,malloc返回的起始内存地址为0x100,你申请的2个连续int内存的地址范围为0x100 ~ 0x107,逐行运行逻辑如下:
int* arr = (int*)malloc(2 * sizeof(int));
此时arr保存的是申请内存的起始地址0x100,指向第一个int的位置。arr = arr + 1;
因为arr是int*类型,加1相当于偏移4字节,此时arr的值变为0x104,指向第二个int的位置。*arr = 11;
对当前arr指向的0x104地址赋值,此时0x104位置的值为11。arr[-1] = 22;
C语言中下标运算a[b]本质等价于*(a + b),因此arr[-1]就是*(arr - 1),arr当前是0x104,减1后得到0x100,对该地址赋值后0x100位置的值为22。int x = arr[0]; // x = 11arr[0]等价于*(arr + 0),取的是0x104地址的值,因此x为11。int y = arr[1]; // y = 194759710arr[1]等价于*(arr + 1),计算后地址为0x108,已经超出了你malloc申请的内存范围,属于访问未初始化的野内存,得到的是随机垃圾值。
预期结果不符的原因
你错误认为偏移后的arr仍然以原始malloc起始地址为基准计算下标,实际上执行arr = arr + 1之后,arr的基准地址已经变为0x104,所有下标运算都以这个新地址为起点。
如果要得到你预期的x == 22、y == 11,只需要修改取值代码为:
int x = arr[-1]; int y = arr[0];
额外注意事项
你修改了malloc返回的原始指针,后续如果直接调用free(arr)会触发未定义行为,free必须传入malloc返回的原始地址,因此做指针偏移前建议额外保存原始指针:
int* original_arr = (int*)malloc(2 * sizeof(int)); int* arr = original_arr + 1; // 后续操作完成后free(original_arr)即可
内容的提问来源于stack exchange,提问作者Irbis
相关产品推荐
相关产品推荐

