C语言结构体的对齐准则
发布时间:2011-06-28 09:41:36 文章来源:www.iduyao.cn 采编人员:星星草
C语言结构体的对齐原则
本文和大家分享的主要是C语言结构体的对其相关原则,希望通过本文的分享,对大家学习C语言http://www.maiziedu.com/course/571/有所帮助吧。
Q:关于结构体的对齐,到底遵循什么原则?
A:首先先不讨论结构体按多少字节对齐,先看看只以1字节对齐的情况:
#include <stdio.h>
#include <string.h>
#define PRINT_D(intValue) printf(#intValue" is %d\n", (intValue));
#define OFFSET(struct,member) ((char *)&((struct *)0)->member - (char *)0)
#pragma pack(1)
typedef struct
{
char sex;
short score;
int age;
}student;
int main()
{
PRINT_D(sizeof(student))
PRINT_D(OFFSET(student,sex))
PRINT_D(OFFSET(student,score))
PRINT_D(OFFSET(student,age))
return 0;
}
输出:
sizeof(student) is 7
OFFSET(student,sex) is 0
OFFSET(student,score) is 1
OFFSET(student,age) is 3
可以看到,如果按1字节对齐,那么结构体内部的成员紧密排列,sizeof(char) == 1, sizeof(short) == 2, sizeof(int) == 4.
修改上面的代码, 去掉#pragma pack语句,代码如下:
#include <stdio.h>
#include <string.h>
#define PRINT_D(intValue) printf(#intValue" is %d\n", (intValue));
#define OFFSET(struct,member) ((char *)&((struct *)0)->member - (char *)0)
typedef struct
{
char sex;
short score;
int age;
}student;
int main()
{
PRINT_D(sizeof(student))
PRINT_D(OFFSET(student,sex))
PRINT_D(OFFSET(student,score))
PRINT_D(OFFSET(student,age))
return 0;
}
运行结果:
sizeof(student) is 8
OFFSET(student,sex) is 0
OFFSET(student,score) is 2
OFFSET(student,age) is 4
此时,各个成员之间就不像之前那样紧密排列了,而是有一些缝隙。这里需要介绍下对齐原则:
此原则是在没有#pragma pack语句作用时的原则(不同平台可能会有不同):
原则A:struct或者union的成员,第一个成员在偏移0的位置,之后的每个成员的起始位置必须是当前成员大小的整数倍;
原则B:如果结构体A含有结构体成员B,那么B的起始位置必须是B中最大元素大小整数倍地址;
原则C:结构体的总大小,必须是内部最大成员的整数倍;
依据上面3个原则,我们来具体分析下: sex在偏移0处,占1字节;score是short类型,占2字节,score必须以2的整数倍为起始位置,所以它的起始位置为2; age为int类型,大小为4字节,它必须以4的整数倍为起始位置,因为前面有sex占1字节,填充的1字节和score占2字节,地址4已经是4的整数倍,所以age的位置为4.最后,总大小为4的倍数,不用继续填充。
继续修改上面的代码,增加#pragma pack语句:
#include <stdio.h>
#include <string.h>
#define PRINT_D(intValue) printf(#intValue" is %d\n", (intValue));
#define OFFSET(struct, member) ((char *)&((struct *)0)->member - (char *)0)
#pragma pack(4)
typedef struct
{
char sex;
short score;
int age;
}student;
int main()
{
PRINT_D(sizeof(student))
PRINT_D(OFFSET(student,sex))
PRINT_D(OFFSET(student,score))
PRINT_D(OFFSET(student,age))
return 0;
}
运行结果:
sizeof(student) is 8
OFFSET(student,sex) is 0
OFFSET(student,score) is 2
OFFSET(student,age) is 4
具体分析下:
有了#pragma pack(4)语句后,之前说的原则A和C就不适用了。实际对齐原则是自身对齐值(成员sizeof大小)和指定对齐值(#pragma pack指定的对齐大小)的较小者。依次原则,sex依然偏移为0, 自身对齐值为1,指定对齐值为4,所以实际对齐为1; score成员自身对齐值为2,指定对齐值为4,实际对齐为2;所以前面的sex后面将填充一个1字节,然后是score的位置,它的偏移为2;age自身对齐值为4,指定对齐为4,所以实际对齐值为4;前面的sex和score正好占用4字节,所以age接着存放;它的偏移为4.
Q:关于位域的问题,空域到底表示什么?
A:它表示之后的位域从新空间开始。
#include <stdio.h>
#include <string.h>
#define PRINT_D(intValue) printf(#intValue" is %d\n", (intValue));
#define OFFSET(struct, member) ((char *)&((struct *)0)->member - (char *)0)
typedef struct
{
int a : 1;
int b : 3;
int : 0;
int d : 2;
}bit_info;
int main()
{
PRINT_D(sizeof(bit_info))
return 0;
}
运行结果:
sizeof(bit_info) is 8
bit_info中的a, b占用4个字节的前4位,到int:0; 时表示此时将填充余下所有没有填充的位,即刚刚的4个字节的余下28位;int d:2; 将从第四个字节开始填充,又会占用4个字节,所以总大小为8.
来源:嵌入式Linux中文站
友情提示:
信息收集于互联网,如果您发现错误或造成侵权,请及时通知本站更正或删除,具体联系方式见页面底部联系我们,谢谢。
其他相似内容:
-
【★C/C++奖励基金-30期★】更新获奖书籍,请选择~ - C/C++ / 非技术区
【★C/C++奖励基金-30期★】
C/C++ 2011-12专家榜
名次...
-
C/c++ 如何按位拷贝呢?
我有一个结构体
strut st_header
{
unsigned short ver:2
unsigned short ping:1
unsgne...
-
uboot上的一点代码,没看明白!
struct in_str {
const char *p;
#ifndef __U_BOOT__
char peek_buf[2];
#endif
int __promptme;
...
-
Debug时为什么变量的地址不变?
是巧合还是某种必然. 是不是因为C中生成的可执行程序存储的地址是相对地址而不是绝对的物理地址.
...
-
关于switch语句。我不知道哪里错了,大侠帮忙bug一下
#include <stdio.h>
int main()
{
int a;
char b;
do{
printf("1.Chines...
-
#pragma section 的 $ 语法
在 ARX 头文件中间过如下三行,放在一起:
#pragma section("ARXCOMMAND$__a")
#pragma section("ARXCOMM...
-
read 问题再现
#define N 205
signed short x[N];
for(i=0;i<N;i++)
{
printf("hello boy!!\n");
...
-
征求一个C语言输入函数?
不知道大家有没有学习过Java? 现在需要一个类似Java的Scanner的函数集, 要求如下:
1. 三个函数: int rea...
-
求一道算法。一个整数,它加上100后是一个完全平方数,再加上168又是一个完全平方数,请问该数是多少?
/*我写了一点,但是有错误,汗*/
/*
...
-
3n+1问题
求救,不知道错在哪里
#include<stdio.h>
int count(int a,int b)
{
int max=0,len=0,a1;
while(a<=b)
{
...