C中字节对齐问题

好多笔试中,会考结构体的sizeof是多少,这就涉及到了字节对齐问题。(VC或GCC编译器,默认按4字节对齐)

什么叫字节对齐?

就是数据在内存中存放的方式,它存放的地址需要是它长度的整数倍。比如单字节放在什么地址都可以,双字节数据只能存放在偶地址上,4字节数只能存放在是4的倍数的地址上。

注意:它与CPU访问的方式无关,32位机器就是按照4字节来访问的,因为它的数据总线是32位,不会以数据在内存中的对齐方式而变化。

一、对于标准数据类型,它的地址是他长度的整数倍就行了。

char:1字节对齐(有符号无符号一样)

short:2

int:4

long:4

float:4

double:8

二、对于非标准类型,对齐方式如下:

1、数组:按照基本数据类型对齐,只要第一个数据对齐了,后面的自然就对齐了。

2、联合体:按照元素中最大的长度对齐。

3、结构体:结构中每个数据都要对齐。

其中,因为结构体对齐最复杂,所以也最常见。

下面举几个结构体例子:

1、struct st1

{
char x1;

int x2;

char x3[10];

};

它占几个字节呢?正确答案是:20

分析如下:char本来占1个字节,因为4字节对齐,所以需要在x1后空出3个字节,接下来才是x2.x3本来占10个字节,但由于最后两个字节后面也需要空出2个字节,所以x3占12个字节。这样4+4+12=20个字节。

2、如下两个类似的结构体,成员相同,只是顺序不同,则所占字节不同。

struct A

{

char a;

int b;

short:c;

};

struct B

{

int b;

char a;

short c;

};

正确答案:A占12个字节,B占8个字节。

分析:A:a(1个字节)之后是b(4个字节),需要在a之后空着3个字节。4+4+4=12.

B:b先占4个字节,紧接着a占1个字节,然后c占2个字节,那么只需要在a之后空1个字节就可以存放c。所以4+2+2=8.

当然,可以不采取默认的对齐方式,可以手工修改任意字节对齐,这个只是修改编译器的对齐方式,只是改变了编译出来的数据的排列方式而已,CPU依旧是按照4字节访问的。

人工修改字节对齐方式有2种方式:

1、#pragma pack(n)与#pragma pack() n字节对齐

如:

#pragma pack (2) /*指定按2字节对齐*/
struct C
{
        char b;
        int a;
        short c;
};
#pragma pack () /*取消指定对齐,恢复缺省对齐*/
sizeof(struct C)值就变为8。

2、__attribute((aligned (n)))与__attribute__((packed))    

使用如下:

struct A

{

char a;

int b;

char a[10];

}__attrubute__ ((aligned(1)));

1字节对齐,则sizeof(A)=15。

struct A

{

char a;

int b;

char a[10];

}__attrubute__ ((packed));

取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐,是GCC特有的语法

问:什么时候需要手动设置对齐方式呢?

:实际工程中,当在不同CPU下,设计通信协议时,或编写硬件驱动程序时(需要用结构体来描述寄存器结构),需要手动设置。即使看起来就自然对齐的也要手动对齐,以免不同的编译器生成的代码不一样。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值