静态与动态变量内存分配位置有差异吗?为何指针打印长度不同?
动态与静态变量的内存分配及指针显示问题解答
一、内存分配位置的限制与差异
- 静态变量(全局变量、
static修饰的局部变量):分配在静态存储区(数据段/BS段),这块内存是程序加载时就固定分配的,大小受程序编译时的符号表、数据量限制,运行时无法扩容。 - 动态变量(
malloc/calloc等分配的变量):分配在堆区,堆的大小受系统虚拟内存上限限制,只要系统有空闲虚拟内存,就能申请(直到触发内存不足错误)。 - 自动变量(普通局部变量):分配在栈区,栈的大小有明确限制(通常几MB,不同系统默认值不同),超出会触发栈溢出。
不存在「动态变量无法分配、但静态变量可分配」的分区。静态存储区、堆、栈是进程地址空间里完全独立的区域,静态变量只会在静态存储区,动态分配只会用堆,彼此不会占用对方的分区。
二、指针打印长度不同的原因
你观察到的动态指针打印更短,和指针本身的大小无关——你用sizeof验证过都是8字节,这是正确的,64位系统下所有指针都是8字节(64位)。
问题出在printf的%p格式输出:它会自动省略地址高位的前导零。比如动态分配的堆地址可能是0x0000000015512a0,打印时就会显示成0x15512a0;而栈地址(比如你的静态/自动变量地址0x7ffc49f6fbe4)高位没有零,所以会完整显示16位十六进制(对应8字节)。
你的偏移实验也能验证这一点:c+67108864其实是给地址加上了2^26(64MB),原本的0x211e2a0加上后变成0x1211e2a0——这里高位多了一个1,所以打印出来的长度就变长了,但本质上还是8字节的指针,只是前导零被省略了而已。
补充:关于你的实验代码
验证指针大小的代码:
int a; int *b=malloc(sizeof(int)); printf("%lu\n%lu",sizeof(&a),sizeof(b));
输出都是8,完全符合64位系统的指针规范,说明所有指针的物理大小是一致的。
指针偏移的代码:
int a, *b; int *c=malloc(sizeof(int)); printf("%p\n%p\n%p",&b,c,c+67108864);
输出的0x1211e2a0就是0x211e2a0 + 0x4000000(67108864的十六进制是0x4000000)的结果,高位补1后就不会被省略,所以显示更长的十六进制串。
内容的提问来源于stack exchange,提问作者Shon_Shon
相关产品推荐
相关产品推荐

