GNU C的一大特点就是__attribute__机制。__attribute__机制能够设置函数属性(Function Attribute)、变量属性(Variable Attribute)和类型属性(Type Attribute)。html
__attribute__语法格式为:__attribute__((attribute-list))。函数
__attribute__对结构体(struct)或共用体(union)进行属性设置:性能
大体有六个参数值能够被设定,即:aligned,packed,transparent_union,deprecated和may_alias。spa
在使用__attribute__参数时,你也能够在参数的先后都加上“__”(两个下划线),例如,使用__aligned__而不是aligned,这样,你就能够在相应的头文件里使用它而不须要关心头文件里是否有重名的宏定义。code
1. aligned(alignment):htm
设定对齐的格式(以字节为单位),例如:对象
struct S { short b[3]; }__attribute__((aligned (8)));
typedef int int32_t __attribute__((aligned(8)));
/*
* 该声明将强制编译器确保(尽量)变量类型为structS或者int32_t的变量在分配空间时采用8字节对齐方式。
*/
如上所述,你能够手动指定对齐的格式,一样,你也可使用默认的对齐方式。若是aligned后面不指定数值,那么编译器将依据你的目标机器状况使用最大最有益的对齐方式。例如:blog
struct S { short b[3]; } __attribute__((aligned)); // 使用默认对齐方式,依据目标机器,使用最大最有益的对齐方式
#include <stdio.h> struct S1 { short b[3]; }; struct S2 { short b[3]; } __attribute__((aligned(8))); struct S3 { short b[3]; } __attribute__((aligned(16))); struct S4 { short b[3]; } __attribute__((aligned(32))); struct S5 { short b[3]; } __attribute__((aligned(64))); struct S6 { short b[3]; } __attribute__((aligned)); int main(int argc, char** argv) { printf("sizeof(struct S1) = %ld\n", sizeof(struct S1)); printf("sizeof(struct S2) = %ld\n", sizeof(struct S2)); printf("sizeof(struct S3) = %ld\n", sizeof(struct S3)); printf("sizeof(struct S4) = %ld\n", sizeof(struct S4)); printf("sizeof(struct S5) = %ld\n", sizeof(struct S5)); printf("sizeof(struct S6) = %ld\n", sizeof(struct S6)); return 0; }
/*
* 输出结果:
* sizeof(struct S1) = 6
* sizeof(struct S2) = 8
* sizeof(struct S3) = 16
* sizeof(struct S4) = 32
* sizeof(struct S5) = 64
* sizeof(struct S6) = 16
*/
注意:__attribute__属性的效力与你的连接器有关,若是你的连接器最大只支持16字节对齐,那么你此时定义32字节对齐也无济于事。内存
#include <stdio.h> struct A { int a; char b; short c; } aa; struct AP { int a; char b; short c; } __attribute__((aligned(16))) ap; struct B { char a; int b; short c; } bb; struct BP { char a; int b; short c; } __attribute__((aligned(4))) bp; struct C { int a; char b; struct AP px; short c; } cc; struct CP1 { int a; char b; struct AP px; short c; } __attribute__((aligned(4))) cp1; struct CP2 { int a; char b; struct AP px; short c; } __attribute__((aligned(8))) cp2; int main(int argc, char** argv) { printf("sizeof(aa) = %lu, sizeof(ap) = %lu\n", sizeof(aa), sizeof(ap)); printf("sizeof(bb) = %lu, sizeof(bp) = %lu\n", sizeof(bb), sizeof(bp)); printf("sizeof(cc) = %lu, sizeof(cp1) = %lu\n", sizeof(cc), sizeof(cp1)); printf("sizeof(cc) = %lu, sizeof(cp2) = %lu\n", sizeof(cc), sizeof(cp2)); return 0; }
/*
* 输出结果:
* sizeof(aa) = 8, sizeof(ap) = 16
* sizeof(bb) = 12, sizeof(bp) = 12
* sizeof(cc) = 48, sizeof(cp1) = 48
* sizeof(cc) = 48, sizeof(cp2) = 48
*/
关于内存对齐:(其中的#pragma pack()在gcc中不多见,具体用法需确认)编译器
① 什么是内存对齐?
不一样类型的数据在内存中按照必定的规则排列;而不是顺序的一个接一个的排放,这就是对齐。
#include <stdio.h> struct Test1 { char c1; short s; char c2; int i; }; struct Test2 { char c1; char c2; short s; int i; }; int main(int argc, char** argv) { printf("sizeof(struct Test1) = %lu\n", sizeof(struct Test1)); printf("sizeof(struct Test2) = %lu\n", sizeof(struct Test2)); return 0; } /* 输出结果 * sizeof(struct Test1) = 12 * sizeof(struct Test2) = 8 */
②为何须要内存对齐?
#pragma pack可以改变编译器的默认对齐方式
#include <stdio.h> #pragma pack(2) struct Test1 { char c1; short s; char c2; int i; }; #pragma pack() #pragma pack(4) struct Test2 { char c1; char c2; short s; int i; }; #pragma pack() int main(int argc, char** argv) { printf("sizeof(struct Test1) = %lu\n", sizeof(struct Test1)); printf("sizeof(struct Test2) = %lu\n", sizeof(struct Test2)); return 0; } /* * 输出结果: * sizeof(struct Test1) = 10 * sizeof(struct Test2) = 8 */
#include <stdio.h> #pragma pack(8) struct S1 { short a; long b; }; struct S2 { char c; struct S1 d; double e; }; #pragma pack() int main() { struct S2 s2; printf("sizeof(struct S1) = %lu\n", sizeof(struct S1)); printf("sizeof(struct S2) = %lu\n", sizeof(struct S2)); printf("%d\n", sizeof(long)); printf("%d\n", (int)&(s2.d) - (int)&(s2.c)); return 0; } /* * 输出结果: * sizeof(struct S1) = 16 * sizeof(struct S2) = 32 * 8 * 8 */
aligned属性被设置的对象占用更多的空间,相反的,使用packed能够减少对象占用的空间。
2. packed:
使用该属性对struct或union类型进行定义,设定其类型的每个变量的内存约束。当用在enum类型定义时,暗示了应该使用最小完整的类型(it indicates that the smallest integral type should be used)。
#include <stdio.h> struct unpacked_struct { char c; int i; }; struct packed_struct_1 { char c; int i; } __attribute__((__packed__)); struct packed_struct_2 { char c; int i; struct unpacked_struct us; } __attribute__((__packed__)); int main(int argc, char** argv) { printf("sizeof(struct unpacked_struct) = %lu\n", sizeof(struct unpacked_struct)); printf("sizeof(struct packed_struct_1) = %lu\n", sizeof(struct packed_struct_1)); printf("sizeof(struct packed_struct_2) = %lu\n", sizeof(struct packed_struct_2)); return 0; }
/*
* 输出:
* sizeof(struct unpacked_struct) = 8
* sizeof(struct packed_struct_1) = 5
* sizeof(struct packed_struct_2) = 13
*/
参考文章:
http://www.cnblogs.com/astwish/p/3460618.html