C中数据类型的值是如何存储在内存中的

How data type value is stored in memory in C

我实际上是 C 的新手,我在使用 gdb 调试 C 程序时尝试过这个。

这是我的程序

int main(){
int a = 4;
int b = 8;
}

然后我用Gdb调试了程序,单步调试了2行汇编代码,设置了ab

的值
mov    DWORD PTR [rbp-0x4],0x4
mov    DWORD PTR [rbp-0x8],0x8 

rbp 的值为 0x7fffffffde70 由于int数据类型有4个字节,栈从高值地址向低值地址增长,所以a的地址必须是0x7fffffffde70 - 0x4 = 0x7fffffffde6c和地址b 必须是 0x7fffffffde70 - 8 = 0x7fffffffde68,它按预期返回了 48。 但是当我在地址 0x7fffffffde6b 0x7fffffffde6a 0x7fffffffde69 打印值时,它打印 0x00000400 0x00040000 0x04000000 这看起来很奇怪,因为 a 有值 4 可以通过仅使用第一个字节和那些3 个地址应该包含 0x0 不是吗?

int 在您的 C 实现中是 32 位。使用十六进制显示所有用于表示值的32位,4用0000000416表示,8用0000000816.[=12表示=]

当一个整数值存储在内存中时,您的 C 实现首先存储它的最低值字节,然后是下一个最低值字节,然后是下一个最低值字节,依此类推。因此,如果 0000000416 存储在地址 7fffffffde6c16 和 0000000816 存储在 7fffffffde6816,则内存内容为:

Address Contents
7fffffffde6816 0816
7fffffffde6916 0016
7fffffffde6a16 0016
7fffffffde6b16 0016
7fffffffde6c16 0416
7fffffffde6d16 0016
7fffffffde6e16 0016
7fffffffde6f16 0016

当您要求调试器从地址 7fffffffde6b16 打印一个 32 位整数时,它从该地址开始加载四个字节,得到 0016 、0416、0016、0016。由于首先存储最低值的字节,因此这些构成了整数 0000040016.

类似地,从 7fffffffde6a16 打印一个 32 位整数会产生字节 0016, 0016, 0416, 0016, 制作 0004000016, 打印一个 32-来自 7fffffffde6916 的位整数产生字节 0016, 0016, 00 16, 0416, 制作 0400000016.

请注意,当堆栈在您的系统中“向下”(向较低地址)增长时,这适用于函数调用堆栈帧的排序方式以及各个“push”和“pop”处理器指令的行为方式。它不控制编译器如何在堆栈帧中安排变量。编译器在框架内放置变量的顺序不需要与声明它们的顺序相匹配。尤其是当你开启优化,变量类型不同的时候,编译器可能会对变量进行不同的排序。

此外,虽然调试器可能能够从任何地址加载 32 位整数,但您的系统可能有对齐规则,要求 32 位整数在普通情况下位于四个字节的倍数处。不要指望常规程序而不是调试器能够从未对齐的地址加载 32 位整数而不产生中断执行的程序错误。