java字节对齐原则_字节对齐详解-----(三)gcc 的字节对齐扩展

本文详细介绍了GCC的字节对齐扩展,包括#pragma pack和__attribute__ ((packed, aligned))的使用,以及如何在C++中进行代码优化,如利用编译器对齐方式、明智使用数据类型、避免不必要的读写依赖等,以提高程序性能。" 130764272,5750663,寻找黄金宝箱:算法解析与多语言实现,"['算法', '编程挑战', 'Java', 'JavaScript', 'Python', 'C语言']
摘要由CSDN通过智能技术生成

gcc 的字节对齐扩展

一、在阅读ffmpeg代码时经常看到类似下面的语句:

#pragma pack(n)

#pragma pack()

__attribute((aligned (8)))

__attribute__ ((packed));

例如:

#    ifdef __GNUC__

static inline uint32_t unaligned32(const void *v)

{

struct Unaligned

{

uint32_t i;

} __attribute__((packed));

return ((const struct Unaligned *) v)->i;

}

struct FieldTest

{

int a;

char b;

char c;

}__attribute__((packed)) ft;

// 取消编译器优化对齐,取实际长度

//----------------------------------------------------

这两种方式是gcc的c扩展,用来对齐的,包括栈对齐,变量地址对齐,内存分配对齐和结构体对齐方式.

Note:在设置新的#pragma pack(n)之前,应该先取消以前的对齐,也就是说要调用一下#pragma pack().

#pragma pack(n)  //n的取值可以为1、2、4、8,在编译过程中按照n个字结对齐

#pragma pack()    //取消对齐,按照编译器的优化对齐方式对齐

__attribute__ ((packed)); //是说取消结构在编译过程中的优化对齐。

__attribute__ ((aligned (n))); //让所作用的成员对齐在n字节自然边界上,如果结构中有成员的长度大于n,则按照机器字长来对齐

gcc手册中说了不建议使用 #pragma,而且#pragma最多只能支持8字节的对齐.

由于不同编译器可能对对齐的实现有区别,在不同编译器编译的程序间进行数据传递就有可能要用到这些东西了.

struct abc {

u32 sid;

u8 p;

union {

int digest[4];

char ctldta[10];

} data;

char dummy[0] __attribute__ ((aligned (64)));

} __attribute__ ((packed));

//__attribute__ ((packed)); 是说取消结构在编译过程中的优化对齐。

//__attribute__ ((aligned (64))); 是说让dummy成员对齐在64-bit自然边界上。

#include

struct FieldTest

{

int a;

char b;

char c;

} __attribute__((aligned(16))) ft; //Aligned by 128 bit

int main(int argc,char** argv)

{

cout<

return 0;

}

//---------------------------------------------------------

g++ packed_test.cpp -o test.exe -Wno-deprecated

./test.exe

the size of FieldTest is 16

人为对齐就是保证每组数据都是4字节的。

例如:

{

char s1[3] ;

long l ;

char s2 ;

}

应改为

{

char s1[3] ;

char s2 ;

long l ;

}

同理,

{

short a ;

long l ;

short b ;

}

应改为

{

short a ;

short b ;

long l ;

}

就是保证每个数据的起始位置符合4字节对齐要求。

若是有奇数个short, 如:

{

short s1;

short s2;

short s3;

long l ;

}

那么要想对齐, 就得手工补足:

{

short s1;

short s2;

short s3;

short temp ;

long l ;

}

这样就不用编译器帮你对齐了。它的最大好处其实是不论1,2,4字节对齐,

编译器生成的结构都是一样的。 这在通信和文件保存方面有莫大的好处。

char也一样, 全应补足为4字节。

二、更改C编译器的缺省字节对齐方式

在缺省情况下,C编译器为每一个变量或是数据单元按其自然对界条件分配空间。一般地,可以通过下面的方法来改变缺省的对界条件:

1). 使用伪指令#pragma pack (n),C编译器将按照n个字节对齐。

2) .使用伪指令#pragma pack (),取消自定义字节对齐方式。

另外,还有如下的一种方式:

1). __attribute((aligned (n))),让所作用的结构成员对齐在n字节自然边界上。如果结构中有成员的长度大于n,则按照最大成员的长度来对齐。

2). __attribute__ ((packed)),取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐。

以上的n = 1, 2, 4, 8, 16... 第一种方式较为常见。

三、应用实例

在网络协议编程中,经常会处理不同协议的数据报文。一种方法是通过指针偏移的方法来得到各种信息,但这样做不仅编程复杂,而且一旦协议有变化,程序修改起来也比较麻烦。在了解了编译器对结构空间的分配原则之后,我们完全可以利用这一特性定义自己的协议结构,通过访问结构的成员来获取各种信息。这样做,不仅简化了编程,而且即使协议发生变化,我们也只需修改协议结构的定义即可,其它程序无需修改,省时省力。下面以TCP协议首部为例,说明如何定义协议结构。其协议结构定义如下:

#pragma pack(1) // 按照1字节方式进行对齐

struct TCPHEADER

{

short SrcPort; // 16位源端口号

short DstPort; // 16位目的端口号

int SerialNo; // 32位序列号

int AckNo; // 32位确认号

unsigned char HaderLen : 4; // 4位首部长度

unsigned char Reserved1 : 4; // 保留6位中的4位

unsigned char Reserved2 : 2; // 保留6位中的2位

unsigned char URG : 1;

unsigned char ACK : 1;

unsigned char PSH : 1;

unsigned char RST : 1;

unsigned char SYN : 1;

unsigned char FIN : 1;

short WindowSize; // 16位窗口大小

short TcpCh

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值