结构的存储分配:
结构在内存中是如何实际存储的呢?编译器按照成员列表的顺序- 一个接-一个地给每个成员分配内存。只有当存储成员时需要满足正确的边界对齐要求时,成员之间才可能出现用于填充的额外内存空间。即以成员最大的字节为准,从第一个开始往后分配内存空间,当成员小于最大类型字节时,就补齐至最大的成员字节数。
下面的一个例子:
#include<stdio.h>
typedef struct node
{
char a; //1字节
float b; //4字节
double c; //8字节
int *p; //由编译器决定
}pnode;
int main(int argc, char const *argv[])
{
/* code */
pnode n;
printf("字节数为:%lu\n",sizeof(n) );
return 0;
}
这里的字节数计算:最大字节数为c变量,8字节,接着分配时:
a :1 sum=1<8
b: 4 sum=1+4<8
c : 8 sum=5+8>8 ,补齐3个字节后再为c分配,sum=5+(3)+8=16
d: 8(指针根据最大字节数来分配) sum=16+8=24
结果为24字节。
改变下顺序
#include<stdio.h>
typedef struct node
{
char a; //1字节
double b; //8字节
float c; //4字节
int *p; //由编译器决定
}pnode;
int main(int argc, char const *argv[])
{
/* code */
pnode n;
printf("字节数为:%lu\n",sizeof(n) );
return 0;
}
输出字节:1+(7)+8+4+(4)+8=32
所以这里就涉及到一个技巧了,你可以在声明中对结构的成员列表重新排列,让那些对边界要求最严格的成员首先出现,对边界要求最弱的成员最后出现。这种做法可以最大限度地减少因边界对齐而带来的空间损失。
有时,我们有充分的理由,决定不对结构的成员进行重排以减少因对齐带来的空间损失。例如,我们可能想把相关的结构成员存储在一起,提高程序的可维护性和可读性。但是,如果不存在这样的理由,结构的成员应该根据它们的边界需要进行重排,减少因边界对齐而造成的内存损失。当程序将创建几百个甚至几千个结构时,减少内存浪费的要求就比程序的可读性更为急迫。在这种情况下,在声明中增加注释可能避免可读性方面的损失。
sizeof操作符能够得出-一个结构的整体长度,包括因边界对齐而跳过的那些字节。如果你必须确定结构某个成员的实际位置,应该考虑边界对齐因素,可以使用offsetof 宏(定义于stddef.h)。
struct ALIGN2 {
char a;
int b;
char C;
};
offsetof( type, member )
type就是结构的类型,member就是你需要的那个成员名。表达式的结果是一个size_ t值,表示这个指定成员开始存储的位置距离结构开始存储的位置偏移几个字节。例如,对前面那个声明而言,
offsetof( struct ALIGN, b )
的返回值是4。