我是靠谱客的博主 外向乌龟,最近开发中收集的这篇文章主要介绍gcc之__attribute__字节对齐参数设置,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

在性能要求比较高的场景下,经常会用到字节对齐,我们可以通过gcc的__attribute__来设置struct的字节对齐,比较常用的就是aligned和packet,本文主要介绍这两种设置字节对齐的用法。

1. aligned - 设置变量对齐

aligned的功能就是设置变量按照指定的字节进行内存对齐,对齐的字节数必须是2的指数,再看一个使用的例子:

// file: test.c
// gcc test.c -o test
#include <stdint.h>
#include <stdio.h>

struct Test1 {
    int64_t a;
    int8_t b;
    int32_t c;
    int8_t d;
};

struct Test2 {
    int64_t a;
    int8_t b __attribute__((aligned(16)));
    int32_t c;
    int8_t d;
};

struct Test3 {
    int64_t a;
    int8_t b;
    int32_t c;
    int8_t d;
} __attribute__((aligned(16)));

int main() {
    struct Test1 t1;
    struct Test2 t2;
    struct Test3 t3;
    printf("sizeof(t1) = %dn", sizeof(t1));
    printf("sizeof(t2) = %dn", sizeof(t2));
    printf("sizeof(t3) = %dn", sizeof(t3));
    printf("t1 &a = 0x%p, &b = 0x%p, &c= 0x%p &d = 0x%pn", &t1.a, &t1.b, &t1.c, &t1.d);
    printf("t2 &a = 0x%p, &b = 0x%p, &c= 0x%p &d = 0x%pn", &t2.a, &t2.b, &t2.c, &t2.d);
    printf("t3 &a = 0x%p, &b = 0x%p, &c= 0x%p &d = 0x%pn", &t3.a, &t3.b, &t3.c, &t3.d);
}

输出是:

$./test
sizeof(t1) = 24
sizeof(t2) = 32
sizeof(t3) = 32
t1 &a = 0x0x7ffe7bb381b0, &b = 0x0x7ffe7bb381b8, &c= 0x0x7ffe7bb381bc &d = 0x0x7ffe7bb381c0
t2 &a = 0x0x7ffe7bb38190, &b = 0x0x7ffe7bb381a0, &c= 0x0x7ffe7bb381a4 &d = 0x0x7ffe7bb381a8
t3 &a = 0x0x7ffe7bb38170, &b = 0x0x7ffe7bb38178, &c= 0x0x7ffe7bb3817c &d = 0x0x7ffe7bb38180

test1为什么是24字节?因为gcc编译程序的时候会遵循两个准则:

  • 结构体变量中成员的偏移量必须是成员大小的整数倍;
  • 结构体总大小必须是所有成员大小的整数倍,也就是说是所有成员大小的公倍数;
  • 结构体的总大小为结构体对齐字节数大小的整数倍。

t2、t3都是32字节,那么他们的内存布局是一样的吗?其实是不一样的,t1、t2、t3的内存布局如下图所示(深色区域为padding):
在这里插入图片描述
在__attribute__变量属性中,还有一个“warn_if_not_aligned”用来检查结构体对齐,它的用法如下:

struct foo {
  int a;
  int b;
} __attribute__ ((warn_if_not_aligned (16)));

上面的代码在编译的时候会报“warning: ‘warn_if_not_aligned’ attribute directive ignored [-Wattributes]”警告错误。
字节对齐实际上做的是偏移量对齐以及长度对齐,对齐会浪费内存空间,那为什么还要做字节对齐呢?原因是为了提高内存系统性能,机器从内存中读取数据时,是按照一定字节(cache_line一般是64B)来获取的,如果不对齐的话,就可能增加读取的次数,降低性能。一般在对性能有极致要求的程序中,会特别关心字节对齐。

2. packed - 设置变量按照1字节对齐

用packed标识结构体,表示的是其成员采用紧凑模式排布,不允许有字节填充,经常用在序列化场景下,如下:

// file: test_packed.c
// gcc test_packed.c -o test_packed
#include <stdio.h>
#include <stdint.h>

struct Test1 {
    int64_t a;
    int8_t b;
    int32_t c;
    int8_t d;
} __attribute__ ((packed));

void main() {
    printf("sizeof(Test1) = %dn", sizeof(struct Test1));
}

结果如下:

$./test_packed
sizeof(Test1) = 14

3. 参考文档

  1. https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#Common-Variable-Attributes

最后

以上就是外向乌龟为你收集整理的gcc之__attribute__字节对齐参数设置的全部内容,希望文章能够帮你解决gcc之__attribute__字节对齐参数设置所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(57)

评论列表共有 0 条评论

立即
投稿
返回
顶部