[英]Structure memory alignment in C
我对以下C程序有疑问
码:
#include <stdio.h>
#include <stdlib.h>
int main()
{
struct a
{
char arr[10];
int i;
float b;
}v[2];
printf("\n %d %d %d \n",v[0].arr, &v[0].i, &v[0].b);
printf("\n %d %d %d \n",v[1].arr, &v[1].i, &v[1].b);
printf("\nHello world!\n");
return 0;
}
输出:
2686712 2686724 2686728
2686732 2686744 2686748
Hello world!
问题:v [0] .arr == 2686712和arr [10]的大小为10字节&v [0] .i <<<<此地址应在数组..之后立即开始,因为array为10字节.. &v [0] .i的地址应从2686712 + 10开始,即2686722为什么&v [0] .i == 2686724而不是2686722
允许编译器在结构的成员之间或末尾(但不能在开头)插入填充。 根据C99标准草案第6.7.2.1
节“ 结构和联合说明符”第13段,其中( 强调我的 ):
在结构对象中,非位字段成员和位字段所在的单元的地址按照声明的顺序增加。 指向经过适当转换的结构对象的指针指向其初始成员(或者,如果该成员是位字段,则指向它所驻留的单元),反之亦然。 结构对象内可能存在未命名的填充,但在其开始处没有。
和第15段:
在结构或联合的末尾可能有未命名的填充。
通过对指针使用%d
格式说明符,您正在调用未定义的行为 ,则应使用%p
。
编译器填充结构成员以使每种数据类型的内容正确对齐。
有关结构填充实际上如何工作的信息,请参见此链接 。 那里有很多非常详细的信息。 另请参阅此链接,以获取针对各种数据类型的英特尔处理器特有的对齐信息。
本质上,因为您有一个10字节的char数组,然后是一个int,所以编译器已在char数组中填充了额外的2个字节,以便int可以在4字节边界上正确对齐(即,地址均匀可被4整除。
就像您这样声明结构:
struct a
{
char arr[10];
char _padding[2];
int i;
float b;
};
出于习惯,我通常分配的char数组的大小可以被4整除。这样一来,编译器就不必为我做这件事,并且可以更轻松地查看内存中的数据结构。
第一:您不应该使用%d
来打印带有printf的指针,而应该使用%p
。
第二:仅保证结构的第一个元素从结构的地址开始。 任何其他成员都可以插入填充字节,具体取决于编译器和体系结构要求。
大多数编译器默认会将成员的struct元素填充为成员大小。 因此在arr
之后将有两个填充字节。
使用struct {...} __attribute__(packed);
如果您希望有一个完整的结构。
在您的系统上,发生4字节对齐。
和
“ int”和“ float”将占用4个字节,“ char”将占用1个字节
1)在您的问题中,您的结构由于顺序而浪费了2个字节
构造一个{
char arr[10];
int i;
float b;
}v[2];
ANS :: 2)我的解决方法是更改“ char arr [10]”的序列,将其放在最后
构造一个
{
int i;
float b;
char arr[10];
}v[2];
现在,如果您要打印地址,那么它将根据您的理解进行打印...
3)内存对齐方式可以根据您的要求(由Compiler使用Google上的“ PRAGMA”搜索“ PRAGMA”提供)进行更改。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.