__attribute__((aligned(n)))和__attribute__((packed))

__attribute__GUN C中极具特设的一大机制,可以用来设置

  • 函数属性(Function Attribute)
  • 变量属性(Variable Attribute)
  • 类型属性(Type Attribute)

这里我们主要阐述用__attribute__((aligned(n)))__attribute__((packed))两个指令对结构体进行属性设置

一、作用简述

__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字节对齐。

二、在结构体类型中的使用方法

2.1 使用格式

/*定义结构体时不对类型重命名*/
struct mystruct
{
    /*成员变量定义*/
}__attribute__() /*(可同时在这定义变量)*/;

struct __attribute__() mystruct
{
    /*成员变量定义*/
}/*(可同时在这定义变量)*/;

/*定义结构体同时对类型进行重命名*/
typedef struct mystruct
{
    /*成员变量定义*/
}__attribute__() MS;

typedef struct __attribute__() mystruct
{
    /*成员变量定义*/
}MS;

2.2 测试代码

#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;
    double b;
    char c;
}__attribute__((aligned(16))) test3;

struct __attribute__((aligned(16))) mystruct4
{
    int a;
    double b;
    char c;
}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;
}

2.3 测试结果

在这里插入图片描述
其中,test1~test4主要进行格式的测试。对于__attribute__((aligned(16))),对齐图示如下(文字描述参照代码中的注释):
在这里插入图片描述
对于其他的n也是这样分析:

  • 在64位操作系统64位编译器的环境下,当n ≥ 8时,内存对齐的字节数是n,不然为8
  • 在32位操作系统32位编译器的环境下,当n ≥ 4时,内存对齐的字节数是n,不然为4

PMS5也可以看出,__attribute__((packed))就是一字节对齐

三、aligned(n)在变量、函数中的使用

3.1 在变量中的使用

C/C++中长度为n字节的基本数据类型的变量在编译时会被编译器默认分配到n字节对齐的内存上。例如,int的长度是4字节,所以int类型变量将被分配到4字节对齐的地址上。我们也可以通过__attribute__((aligned(n)))来改变这种默认状态。

int a __attribute__ ((aligned (16))) = 0;

这样就把a分配到了16字节对齐的地址上。

3.2在函数中的使用

和改变变量的默认对齐状态一样,也可以通过__attribute__((aligned(n)))来改变函数的自然对齐状态。

void __attribute__ ((aligned (64))) func(void)
{
    /*功能实现代码*/
}

关于__attribute__这里只浅显地总结这么一点东西,如果需要更加丰富的内容,请查阅:
GCC手册:使用GUN编译器集合(GCC)类型属性

发布了16 篇原创文章 · 获赞 1 · 访问量 4440

猜你喜欢

转载自blog.csdn.net/weixin_43955214/article/details/104176988