关于指针算术(Pointer Arithmetic)与malloc的三个技术问题咨询
测试代码
#include <stdio.h> #include <stdlib.h> int main() { int *ptr = malloc(100); printf("base : %p\n", ptr); printf("\n"); printf("base+1 : %p\n", ptr+1); ptr+= 100; *ptr = 90; printf("addr: %p val : %d\n", ptr, *ptr); return 0; }
运行输出
base : 0x5621e46412a0 base+1 : 0x5621e46412a4 addr: 0x5621e4641430 val : 90
问题解答
调用malloc(100)是否会返回100字节的内存空间?
是的,malloc(100)会请求系统分配至少100字节的连续内存块。只要系统有足够空闲内存,就会返回指向该内存块起始地址的指针。实际分配的内存可能略多于100字节(比如为了内存对齐或内存管理的额外开销),但标准保证你可以安全使用请求的100字节空间。此处未对malloc的返回地址进行类型转换,已知malloc返回void*类型,为何ptr+1会递增4字节?
在C语言中,void*类型指针赋值给其他类型指针时会自动完成隐式类型转换。这里ptr是int*类型,指针算术的偏移量是基于指针指向的类型大小计算的:指针加减整数时,实际偏移的字节数等于整数 × 指针指向类型的大小。你的系统中int占4字节,所以ptr+1会自动偏移4字节。执行ptr+=100后,是否相当于偏移了400字节?为何此时赋值未触发Segmentation Fault?
是的,ptr += 100对于int*类型来说,等价于偏移了100 × sizeof(int) = 400字节。此时ptr已经指向了最初分配的100字节内存块之外,属于未定义行为。
未触发Segmentation Fault只是巧合:Segmentation Fault是操作系统在程序访问无权限的内存区域时才会触发的错误。你偏移后的地址可能刚好落在进程的地址空间范围内(比如malloc分配内存周边的空闲区域),操作系统暂时没有拦截,但这种操作完全不安全——后续的内存操作可能覆盖这个值,或者在其他环境、其他执行时机直接触发崩溃。未定义行为的结果不可预测,绝对不能依赖它不报错。
内容的提问来源于stack exchange,提问作者shankar m

