C语言中int与long long内存分配实测偏移异常的疑问
C语言变量地址差异常的原因分析
你遇到的问题核心是混淆了指针减法的计算规则,以及测试代码中的格式符与类型不匹配导致的输出错误,以下是具体分析:
1. 指针减法的本质规则
C语言中,两个指向同类型变量的指针相减,结果是ptrdiff_t类型的整数,代表的是两个指针之间相隔的元素个数,而非直接的内存字节差。实际字节差的计算公式是:
字节差 = 指针减法结果 × sizeof(指针指向的类型)
2. 栈变量的地址分布
栈内存的生长方向是从高地址向低地址,所以先声明的变量会占据更高的内存地址,后声明的变量地址更低。比如你代码中先声明ai,再声明bi,那么&ai的地址会比&bi大。
3. 测试代码的问题分析
(1)int变量部分
假设ai的地址是0x1008,bi的地址是0x1000(栈向下生长,间隔8字节,可能受编译器栈对齐策略影响),那么:
&bi - &ai的计算:(0x1000 - 0x1008) / sizeof(int) = (-8)/4 = -2- 你将这个有符号的
ptrdiff_t强转为unsigned long,再用%llu(对应unsigned long long)输出,类型不匹配导致输出错误值,这就是你看到“地址差为8”的原因。
正确的输出方式应该直接计算字节差,或用对应格式符输出指针减法结果:
// 输出字节差 printf("%llu\n", (unsigned long long)(&bi) - (unsigned long long)(&ai)); // 输出元素个数(使用有符号格式符) printf("%td\n", &bi - &ai);
(2)long long变量部分
同理,先声明的a地址高于后声明的b,若两者地址差为-4字节(不符合long long的8字节对齐规则,大概率是格式符不匹配导致的错误输出),&b - &a的结果为(-4)/8 = 0(整数除法截断),强转后用%llu输出会得到错误值,让你误以为“地址差为4”。
4. 编译器内存对齐的影响
编译器会根据目标平台的对齐规则对栈变量进行对齐,比如long long通常要求对齐到8字节边界,int对齐到4字节边界。这可能导致连续变量间出现填充字节,使实际字节差大于变量本身大小,但不会改变指针减法按元素个数计算的规则。
正确的测试方式应直接输出变量地址值,再手动计算字节差,而非依赖指针减法的结果。
内容的提问来源于stack exchange,提问作者dalvol.amsi
相关产品推荐
相关产品推荐

