【理论实践】用alignas代替#pragma pack

知识背景:

       字段对齐,使对象或成员的地址满足一定要求。4字节对齐就是地址都是4的整数倍,这个必须是2的N次方。

       为什么要对齐?一方面,如果4字节对齐了,对于128个内存空间,实际只有32个独立地址,相当于管理地址变少了,文件系统经常这么用,用少的寻址空间,管理更大的磁盘空间。另一方面,一些硬件设计上了,为了一些考虑,强制要求地址要符合指定规则。

       对齐有什么影响?最直接的影响就是占用内在大小变了,会影响sizeof,举例如下:

struct A
{
       int a;
       char b;
       int c;
};
        sizeof(A)大小并不是4+1+4=9,而是12,4+4+4。

        为什么要改变对齐?强转之下,受对齐影响,不正确了。容易遇到的场景就是:收到网络字节流,消息头是结构化的,定义一个结构体,强转读取对应的字段


       怎么更改对齐大小?

       c++11之前,我们经常这么用

       #pragma pack(push)   //保存当前的对齐方式
       #pragma pack(1)         //指定接下来,1字节对齐
       //定义你的结构体
       #pragma pop(pop)       //指定恢复保存的对齐方式


        明显这个相当暴力了,如果每个人都这么做,至少3行代码。为了省事,总容易有人不push和pop,直接改,某人就会在不知情的情况下,包含了这个头文件,进而受影响……

        于是,编译器突破规范,定义了扩展:__declspec(align(n))等,记住,是等,也就是各做各的,不统一,于是c++11火速规范化制定了这个标准:alignas 和alignof。

        a开头的关键字,排在最前面,有人会郁闷吧,总看到,却不知道是什么,我从误区开始,逐步解释一下。

        用法:alignas(t)  define;   t可以是个常量表达式,也可以是具体的大小,也可以是一个类型。 define是原本的定义语句,例如:

        alignas(int) int b;

        struct alignas(33) s

        {

                int a;

        };

        alignof(type),和sizeof非常类似,只是返回对应类型的对齐大小,例如:

         cout << alignof(s);           //返回s的对齐方式

         cout << alignof(s::a) ;      //返回s成员的对齐方式


理论实践

        知识讲完了,开始错误之路吧

        一、对齐不是2的N次方

struct alignas(3) A    //error: requested alignment is not a power of 2
{
        char a;
        char b;
        char c;
        char d;
};

        二、理解错了对齐对象

struct alignas(2) A
{
        char a;
        char b;
        char c;
        char d;
};
if(sizeof(A) == 8)
       alignas修饰结构体时,不是对齐结构体每个成员,而是对齐结构体本身,所以大小不是4*2=8,则是4不变。如果再增加一个char成员,则大小6, 不是5。

       这样去理解结构体对齐:A对齐了,A+sizeof(A)是下一个A元素的地址,需要同样满足对齐,所以需要补空间1。


        三、对齐低于结构体成员最大对齐

struct alignas(2) A
{
        int a;
        char b;
};
        sizeof(A)不是6,而是8,因为a已经是4对齐了,所以b之后会补到8。   alignas(16)则大小是16。

         四、分析一下复杂的,就毕业了,sizeof(B)是多少?128

struct alignas(32) A
{
        int a;
        alignas(8) char b;
};

struct B
{
        A a;
        A b;
        alignas(1) char c;
        A d;
};
          

          以后,再怀疑字节对齐时,请用alignof输出实际的对齐方式看看,不用再去打印内存或调试了。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值