为什么 C 中的 64 位指针只使用 4 个字节而不是预期的 8 个字节?

Mar*_*wra 0 c linux 64-bit pointers

我正在努力成为“一个真正的人”,也就是从 C++ 转向 C。指针和 malloc 有时会让人感到困惑。我正在使用没有任何标志的 gcc,64 位 Linux。

所以我的第一个问题是:

int* c;
int* d;
void* shared = malloc(sizeof(int)*2);
c = shared;
d = shared + sizeof(int);
*c = 123;
*d = 321;

printf("c: %p, *c: %i\n", (void*)c, *c);
printf("d: %p, *d: %i\n", (void*)d, *d);
printf("sizeof(c): %lu, sizeof(d): %lu\n", sizeof(c), sizeof(d));
Run Code Online (Sandbox Code Playgroud)

输出:c:0x1c97050,*c:123 d:0x1c97054,*d:321 sizeof(c):8,sizeof(d):8

将两个内存地址转换为十进制并检查它们的差异,得到 4。这意味着它们在内存中彼此相距 4 个字节?这意味着 int 用 4 个字节表示,sizeof(int) = 4。

但是由于 64 位内存,一个指针(我猜是任何类型的指针,但在我们的例子中是一个 int)是用 8 个字节表示的?这意味着我犯了一个错误,只分配了 4 个字节而不是所需的 8 个字节(int 而不是 int*)。

但为什么我没有丢失任何数据呢?纯粹是巧合/运气?

Joh*_*ode 7

指针对象(cd)占用的存储与数据(这些指针指向的对象)占用的存储无关。

这是一个假设的内存映射,显示了如何布局这些值地址cd凭空组成,假设大端布局):

  Item            Address                0x01  0x02  0x03  0x04
  ----            -------                ----  ----  ----  ----
shared            0x0000000001c97050       00    00    00    7b
                  0x0000000001c97054       00    00    01    41
                  ...    
     c            0x000000fffff86400       00    00    00    00
                  0x000000fffff86404       01    c9    70    50
     d            0x000000fffff86408       00    00    00    00
                  0x000000fffff8640c       01    c9    70    54
Run Code Online (Sandbox Code Playgroud)

在您的malloc调用中,您分配了空间来存储 2 个int对象,每个对象占用 4 个字节。shared位于地址 的第一个元素0x0000000001c97050存储4 字节值 123,位于地址 的第二个元素0x0000000001c97054存储 4 字节值321

c位于地址 处的指针0x000000fffff86400存储 的第一个元素的8 字节shared地址,即0x0000000001c97050d类似地,位于 address 处的指针0x000000fffff86408存储共享的第二个元素的地址,即0x0000000001c97054

TL;DR - 您为数据分配了正确的内存量,这才是最重要的。

无端咆哮

我正在努力成为“一个真正的男人”,也就是从 C++ 转向 C

学习 C 并不会让你更有男子气概;它使你成为了解 C 的人。围绕 C 语言、C 编程和 C 程序员存在着许多糟糕的神话。是的,它的低级抽象迫使你时刻保持警惕,但这并不会让你变得有男子气概,它只会让你变得偏执。C 是适用于相当狭窄的应用程序领域(系统编程、非图形服务器端处理等)的正确工具,但对于一般应用程序编程,它已经被更易于使用的语言所掩盖。

此外,真正的程序员使用 Fortran