__attribute__
是GUN C
中极具特设的一大机制,可以用来设置
函数属性(Function Attribute)
变量属性(Variable Attribute)
类型属性(Type Attribute)
这里我们主要阐述用__attribute__((aligned(n)))和__attribute__((packed))两个指令对结构体进行属性设置
__attribute__
与结构体
理论
__attribute__((aligned(n))) //采用n字节对齐
__attribute__((packed)) //采用1字节对齐
__attribute__((aligned(n)))
中,n的有效参数为2的幂值,32位最大为2 ^ 32
,64位为2 ^ 64
,这个时候编译器会将让n与默认的对齐字节数进行比较,取较大值为对齐字节数,与#pragma pack(n)恰好相反。
*__attribute__((packed))
则为取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐,也就是采用1字节对齐。
在结构体类型中的使用方法如下:
/*定义结构体时不对类型重命名*/
struct mystruct
{
/*成员变量定义*/
}__attribute__() /*(可同时在这定义变量)*/;
struct __attribute__() mystruct
{
/*成员变量定义*/
}/*(可同时在这定义变量)*/;
/*定义结构体同时对类型进行重命名*/
typedef struct mystruct
{
/*成员变量定义*/
}__attribute__() MS;
typedef struct __attribute__() mystruct
{
/*成员变量定义*/
}MS;
注意:
在64位操作系统64位编译器的环境下,当n ≥ 8时,内存对齐的字节数是n,不然为8
在32位操作系统32位编译器的环境下,当n ≥ 4时,内存对齐的字节数是n,不然为4
实践
#include <stdio.h>
typedef struct mystruct1
{ //in64_64 in32_32
int a; //(4 + 4) 4
double b;// 8 8
char c; //(1 + 15) (1 + 3)
}__attribute__((aligned(16))) AMS1;//in 64_64:32; in 32_32:16
typedef struct __attribute__((aligned(16))) mystruct2
{ //in64_64 in32_32
int a; //(4 + 4) 4
double b;// 8 8
char c; //(1 + 15) (1 + 3)
}AMS2; //in 64_64:32; in 32_32:16
struct mystruct3
{
int a; // 4 + 4
double b; //8
char c; // 1+15
}__attribute__((aligned(16))) test3;
struct __attribute__((aligned(16))) mystruct4
{
int a; // 4 + 4
double b; // 8
char c; // 1 + 16
}test4;
typedef struct mystruct5
{
int a; //4
double b;//8
char c; //1
}__attribute__((packed)) PMS5;//in 64_64:13; in 32_32:13
typedef struct mystruct6
{ //in64_64 in32_32
int a; //(4 + 4) 4
double b;// 8 8
char c; //(1 + 7) (1 + 3)
}__attribute__((aligned(8))) A8MS6;//in 64_64:24; in 32_32:16
typedef struct mystruct7
{ //in64_64 in32_32
int a; //(4 + 4) 4
double b;// 8 8
char c; //(1 + 7) (1 + 3)
}__attribute__((aligned(2))) A2MS7;//in 64_64:24; in 32_32:16
typedef struct mystruct8
{ //in64_64 in32_32
int a; //(4 + 4) 4
double b;// 8 8
char c; //(1 + 15) (1 + 19)
}__attribute__((aligned(32))) A32MS8;//in 64_64:32; in 32_32:32
int main(void)
{
AMS1 test1;
AMS2 test2;
printf("sizeof(test1) = %d\n", (int)sizeof(test1));
printf("sizeof(test2) = %d\n", (int)sizeof(test2));
printf("sizeof(test3) = %d\n", (int)sizeof(test3));
printf("sizeof(test4) = %d\n", (int)sizeof(test4));
printf("sizeof(PMS5) = %d\n", (int)sizeof(PMS5));
printf("sizeof(A8MS6) = %d\n", (int)sizeof(A8MS6));
printf("sizeof(A2MS7) = %d\n", (int)sizeof(A2MS7));
printf("sizeof(A32MS8) = %d\n", (int)sizeof(A32MS8));
return 0;
}
#include <stdio.h>
typedef struct struct_test1
{
int a; // 4
double b; // 8
}ST1;
int main(void)
{
printf("__alignof(char ) = %d\n", __alignof(char )); //1
printf("__alignof(short ) = %d\n", __alignof(short )); //2
printf("__alignof(int ) = %d\n", __alignof(int )); //4
printf("__alignof(long ) = %d\n", __alignof(long )); //8
printf("__alignof(long long) = %d\n", __alignof(long long )); //8
printf("__alignof(float ) = %d\n", __alignof(float )); // 4
printf("__alignof(double ) = %d\n", __alignof(double )); //8
printf("__alignof(ST1 ) = %d\n", __alignof(ST1 )); //8 ???????
return 0;
}
__alignof操作返回数据类型或者指定数据项的分界对齐。实际上的数据对齐根据硬件系统不同而不同,因为该需求是由机器设置的
__attribute__
与变量
C/C++中长度为n字节的基本数据类型的变量在编译时会被编译器默认分配到n字节对齐的内存上。例如,int的长度是4字节,所以int类型变量将被分配到4字节对齐的地址上。我们也可以通过__attribute__((aligned(n)))
来改变这种默认状态。
int a __attribute__ ((aligned (16))) = 0;
这样就把a分配到了16字节对齐的地址上。
__attribute__
与函数
和改变变量的默认对齐状态一样,也可以通过__attribute__((aligned(n)))来改变函数的自然对齐状态。
void __attribute__ ((aligned (64))) func(void)
{
/*功能实现代码*/
}