C 一个 unsigned int 怎么可能只占用两个字节?
C how could an unsigned int only takes two bytes?
我正在研究指针,我注意到一件奇怪的事情。
我有一个结构如下:
typedef struct list_element_struct {
uint32_t x;
uint32_t y;
uint32_t z;
struct list_element_struct *next;
}list_element;
据我所知,unsigned int的大小是4个字节,指针的大小是8个字节。这里也有 8 个字节对齐,所以这个结构的大小是 24 个字节。
我已经用 list_element els[5];
初始化了上述结构对象的列表,并且还用 memset(els,0,5*sizeof(list_element));
将其中的每条数据设置为 0
现在我正在尝试使用以下代码查看它们的内存位置:
printf("%p start location of els\n", &(els));
printf("%p start location of els->x\n", &(els->x));
printf("%p start location of els->y\n", &(els->y));
printf("%p start location of els->z\n", &(els->z));
printf("%p start location of els->next(pointer)\n", &(els->next));
printf("%p start location of els+1\n", &(els[1]));
我打印出来的是:
0x7ffeeba4a970 start location of els
0x7ffeeba4a970 start location of els->x
0x7ffeeba4a974 start location of els->y
0x7ffeeba4a978 start location of els->z
0x7ffeeba4a980 start location of els->next(pointer)
0x7ffeeba4a988 start location of els+1
奇怪的是。为什么 els->z 只占用两个字节?它真的应该像 x 和 y 一样取 4。
这些数字是十六进制的。 0x7ffeeba4a978
和 0x7ffeeba4a980
之间的差异不是 2,而是 8。
为了防止你的下一个问题,它是 8 而不是 4 的原因可能是由于对齐要求。许多 64 位系统要求或更愿意将其 8 字节指针对齐到 8 字节边界,即对齐到 8 的倍数的地址(以便它们的最低有效十六进制数字为 8
或 0
).所以编译器在 z
和 next
之间留下 4 个字节的填充来实现这一点。
地址显示为十六进制值
0x7ffeeba4a978 start location of els->z
0x7ffeeba4a980 start location of els->next(pointer)
所以(考虑最后两个十六进制数字)你有
0x80
-
0x78
====
8
因为0x80
等于0x70
+十进制16
或十六进制0x10
.
十六进制数字从小到大为
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F and the next number is 0x10.
编译器在数据成员 z
之后放置了一个等于 4 字节的填充用于对齐。
我正在研究指针,我注意到一件奇怪的事情。
我有一个结构如下:
typedef struct list_element_struct {
uint32_t x;
uint32_t y;
uint32_t z;
struct list_element_struct *next;
}list_element;
据我所知,unsigned int的大小是4个字节,指针的大小是8个字节。这里也有 8 个字节对齐,所以这个结构的大小是 24 个字节。
我已经用 list_element els[5];
初始化了上述结构对象的列表,并且还用 memset(els,0,5*sizeof(list_element));
现在我正在尝试使用以下代码查看它们的内存位置:
printf("%p start location of els\n", &(els));
printf("%p start location of els->x\n", &(els->x));
printf("%p start location of els->y\n", &(els->y));
printf("%p start location of els->z\n", &(els->z));
printf("%p start location of els->next(pointer)\n", &(els->next));
printf("%p start location of els+1\n", &(els[1]));
我打印出来的是:
0x7ffeeba4a970 start location of els
0x7ffeeba4a970 start location of els->x
0x7ffeeba4a974 start location of els->y
0x7ffeeba4a978 start location of els->z
0x7ffeeba4a980 start location of els->next(pointer)
0x7ffeeba4a988 start location of els+1
奇怪的是。为什么 els->z 只占用两个字节?它真的应该像 x 和 y 一样取 4。
这些数字是十六进制的。 0x7ffeeba4a978
和 0x7ffeeba4a980
之间的差异不是 2,而是 8。
为了防止你的下一个问题,它是 8 而不是 4 的原因可能是由于对齐要求。许多 64 位系统要求或更愿意将其 8 字节指针对齐到 8 字节边界,即对齐到 8 的倍数的地址(以便它们的最低有效十六进制数字为 8
或 0
).所以编译器在 z
和 next
之间留下 4 个字节的填充来实现这一点。
地址显示为十六进制值
0x7ffeeba4a978 start location of els->z
0x7ffeeba4a980 start location of els->next(pointer)
所以(考虑最后两个十六进制数字)你有
0x80
-
0x78
====
8
因为0x80
等于0x70
+十进制16
或十六进制0x10
.
十六进制数字从小到大为
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F and the next number is 0x10.
编译器在数据成员 z
之后放置了一个等于 4 字节的填充用于对齐。