attribute与字节对齐

来源:互联网 发布:linux 硬盘分区 编辑:程序博客网 时间:2024/06/06 05:36

1. __attribute__机制

GNU C的一大特色就是__attribute__机制。__attribute__可以设置函数属性(Function Attribute)、变量属性(Variable Attribute)和类型属性(Type Attribute)。

__attribute__书写特征是:__attribute__前后都有两个下划线,并切后面会紧跟一对原括弧,括弧里面是相应的__attribute__参数。

__attribute__语法格式为:__attribute__ ((attribute-list))

其位置约束为:放于声明的尾部之前。

我们只讨论类型属性。其他信息参考如下:

http://blog.chinaunix.net/u1/59740/showart_482955.html

http://www.unixwiz.net/techtips/gnu-c-attributes.html

http://gcc.gnu.org

2. 类型属性

关键字__attribute__也可以对结构体(struct)或共用体(union)进行属性设置。大致有六个参数值可以被设定,即:aligned, packed, transparent_union, unused, deprecated may_alias

在使用__attribute__参数时,你也可以在参数的前后都加上“__”(两个下划线),例如,使用__aligned__而不是aligned,这样,你就可以在相应的头文件里使用它而不用关心头文件里是否有重名的宏定义。

 

2.1. aligned (alignment)

该属性设定一个指定大小的对齐格式(以字节为单位),例如:

struct S {

short b[3];

} __attribute__((aligned (8)));

typedef int int32_t__attribute__ ((aligned (8)));

该声明将强制编译器确保(尽它所能)变量类型为struct S或者int32_t的变量在分配空间时采用8字节对齐方式。

如上所述,你可以手动指定对齐的格式,同样,你也可以使用默认的对齐方式。如果aligned后面不紧跟一个指定的数字值,那么编译器将依据你的目标机器情况使用最大最有益的对齐方式。例如:

struct S {

short b[3];

} __attribute__((aligned));

这里,如果sizeofshort)的大小为2byte),那么,S的大小就为6。取一个2的次方值,使得该值大于等于6,则该值为8,所以编译器将设置S类型的对齐方式为8字节。

aligned属性使被设置的对象占用更多的空间,相反的,使用packed可以减小对象占用的空间。

需要注意的是,attribute属性的效力与你的连接器也有关,如果你的连接器最大只支持16字节对齐,那么你此时定义32字节对齐也是无济于事的。

2.2. packed

 使用该属性对struct或者union类型进行定义,设定其类型的每一个变量的内存约束。当用在enum类型 定义时,暗示了应该使用最小完整的类型(it indicates thatthe smallest integral type should be used)。

 下面的例子中,packed_struct类型的变量数组中的值将会紧紧的靠在一起,但内部的成员变量s不会被“pack”,如果希望内部的成员变量也被packed的话,unpacked-struct也需要使用packed进行相应的约束。

struct unpacked_struct

{

     char c;

     int i;

};

         

struct packed_struct

{

    char c;

    int  i;

    struct unpacked_struct s;

}__attribute__((__packed__));

 

2.3. 变量属性与类型属性举例

 下面的例子中使用__attribute__属性定义了一些结构体及其变量,并给出了输出结果和对结果的分析。

程序代码为:

struct p

{

int a;

char b;

short c;

}__attribute__((aligned(4))) pp;

struct m

{

char a;

int b;

short c;

}__attribute__((aligned(4))) mm;

struct o

{

int a;

char b;

short c;

}oo;

struct x

{

int a;

char b;

struct p px;

short c;

}__attribute__((aligned(8))) xx;

int main()

{

printf("sizeof(int)=%d,sizeof(short)=%d.sizeof(char)=%d/n",sizeof(int),sizeof(short),sizeof(char));

printf("pp=%d,mm=%d /n", sizeof(pp),sizeof(mm));

printf("oo=%d,xx=%d /n", sizeof(oo),sizeof(xx));

return 0;

}

输出结果:

sizeof(int)=4,sizeof(short)=2.sizeof(char)=1

pp=8,mm=12

oo=8,xx=24

分析:

sizeof(pp):

sizeof(a)+sizeof(b)+sizeof(c)=4+1+1=6<8所以sizeof(pp)=8

sizeof(mm):

sizeof(a)+sizeof(b)+sizeof(c)=1+4+2=7

但是a后面需要用3个字节填充,但是b4个字节,所以a占用4字节,b占用4个字节,而c又要占用4个字节。所以sizeof(mm)=12

sizeof(oo):

sizeof(a)+sizeof(b)+sizeof(c)=4+1+2=7

因为默认是以4字节对齐,所以sizeof(oo)=8

sizeof(xx):

sizeof(a)+ sizeof(b)=4+1=5

sizeof(pp)=8;xx是采用8字节对齐的,所以要在ab后面添3个空余字节,然后才能存储px

4+1+3+8+1=17

因为xx采用的对齐是8字节对齐,所以xx的大小必定是8的整数倍,即xx的大小是一个比17大又是8的倍数的一个最小值,由此得到

17<24,所以sizeof(xx)=24

 

原创粉丝点击