PAYATHON 2026

为什么 int 数组的十六进制地址相差 4,实际表示间隔 4 字节?

数据阿明

这些地址之间的间隔是 4 字节,也就是 32 位。这里容易混淆的是:一个十六进制数字可以用 4 个二进制位表示,但地址差值表示的是地址增加的数值。

先计算地址差值

十六进制中的 c 等于十进制的 12,这些地址的末位依次是:

十六进制:0、4、8、c
十进制:  0、4、8、12

相邻地址相减:

0x7ffd0fd676f4 - 0x7ffd0fd676f0 = 0x4 = 4
0x7ffd0fd676f8 - 0x7ffd0fd676f4 = 0x4 = 4
0x7ffd0fd676fc - 0x7ffd0fd676f8 = 0x4 = 4

在这里的 Ubuntu 环境中,内存按字节寻址。地址每增加 1,就向后移动一个字节,所以地址差 0x4 表示相差 4 字节。

为什么不能把 4 再乘以 4 位?

“一个十六进制数字对应 4 位二进制数”说的是数值的表示方式。例如:

十六进制 0x4 = 二进制 0100 = 十进制 4

0100 是用四个二进制位表示数值 4,数值本身仍然是 4,不能把它理解为“4 个单位,每个单位 4 位”。

地址以十六进制显示时,每个十六进制位表示地址数值的一部分,地址差值的单位仍然是字节。换算如下:

地址差:0x4 = 4 字节
位数:  4 × 8 = 32 位

用 C 代码验证

数组元素连续存放,相邻元素的起始位置相差一个元素的大小。可以同时打印元素大小、地址和指针差值:

#include <stdio.h>

int main(void)
{
    int a[4] = {0};

    printf("sizeof(int) = %zu bytes\n", sizeof(int));

    for (size_t i = 0; i < sizeof(a) / sizeof(a[0]); ++i) {
        printf("a[%zu]: %p\n", i, (void *)&a[i]);
    }

    printf("pointer difference = %td\n", &a[1] - &a[0]);
    return 0;
}

如果该环境中的 sizeof(int) 为 4,每个元素就占 4 字节,相邻元素的起始地址也相差 4 字节。实际打印出的地址可能与问题中不同。

最后一行的指针差值是 1。在 C 中,同一数组内两个 int * 相减,得到的是相隔的元素数量。这里相隔一个 int 元素,对应的存储空间大小是 sizeof(int) 字节。

注意 sizeof 的单位

sizeof(int) 的单位是 C 语言中的字节。题目所述的 Ubuntu 环境中,一个字节为 8 位,因此 sizeof(int) == 4 对应 32 位。

C 语言并不保证所有平台上的 int 都是 4 字节。编写跨平台代码时,可以用 sizeof(int) 或 sizeof(a[0]) 获取实际大小;一个字节的位数可以通过 <limits.h> 中的 CHAR_BIT 获取。

备注:内容仅供参考。