You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 23:40:42