学习笔记:alignas用法

struct Test{
    char arr[9];
    alignas(16) int a;
    double b;
    char c;
};
 
  
int main()
{
    auto sizeof_test = sizeof(Test);
    auto alignof_test = alignof(Test);
 
  
    auto offsetof_a=offsetof(Test,a);
    auto offsetof_b=offsetof(Test,b);
    auto offsetof_c=offsetof(Test,c);
 
  
    return 0;

}

问题1) 什么是对齐。
举例说明,某个int类型的对象,要求其存储地址的特征是4的整倍数。例如0x0000CC04。我们把地址值0x0000CC04除以4,余数0,那么这个对象的地址就是对齐的。

问题2) 为什么要对齐。
举例说明,对于int数据,硬件只能在4的倍数的地址读写,假设某int对象的地址是0x0000CC06,则硬件先读取0x0000CC04开始的4个字节,
取其0x0000CC06, 0x0000CC07。硬件然后读取0x0000CC08开始的4个字节,取其0x0000CC08, 0x0000CC09。将两次读取的有用信息拼接即可。
显然,效率不高。更严重的,硬件会报错,程序执行不下去。
 
  

问题3) x86体系下,用#pragma pack(1) 改变结构体中int成员的对齐属性,也没报错呀
只能说x86容忍性高,程序正常跑,不见得效率没有降低。


问题4) C++11的alignas是什么。

改变一个数据类型的对齐属性。在例子中,Test::a的对齐值变成16,意味着a的地址值必须能被16整除。
考察a的偏移值是16,意味着arr[9]后面被插入填充用的7个字节了。
 
  
 
  
问题5) 上例中,只是a相对结构体首地址的偏移值16,如果结构体首地址的值是0x0000CC01,然后+16 = 0x0000CC11,显然不满足地址值的16倍数对齐了
在哪里创建Test当然是很重要的,为了防止上述事件发生,需要编译器和程序员的共同努力,但主要担子还在编译器上。例如在函数栈上创建一个Test对象,编译器必须选择一个好地方才行。

问题6) 为什么sizeof(Test)是48
offsetof(a)=16,a本身长4字节,b的偏移本应是20。
但是考虑到b的类型是double,其默认对齐值是8。20不是8的倍数,填充4个垃圾字节,现在到达偏移值24。
所以b的真正偏移值是24,b占8个字节。
现在到达c,c的偏移值是32,c本身占1个字节,整个test的长度貌似是33。
可是你要考虑test数组,例如数组test kk[2]。kk[1].a, 相对于数组首地址的偏移为33+16=49。这个地址不满足a的对齐了。

但是在c的后面填充15个垃圾字节,则 kk[1].a的地址 =  kk的首地址值 + kk[0]长度48 + kk[1].a偏移值16

假设编译器把kk的首地址值放置的位置使:   
kk的首地址值  /  16 = 0
kk[0]长度48 / 16 = 0
kk[1].a偏移值16 / 16 = 0
则  kk[1].a的地址 / 16 = 0

问题7)  为什么alignof(Test)是16
由于对齐值只能是2,4,8等2的幂,所以大的对齐值一定满足小的对齐需求。例如我按照16字节对齐了,当然也满足8字节对齐,4自己对齐,2字节对齐,1字节对齐了。
整个结构体的对齐值,就是各成员对齐值,最大的那个。
 
   
问题8)alignas(2) int a;  可以实现吗?
C++11规定,只能放大对齐值,而int的原始对齐值是4,现在你要求按2对齐,编译器会忽略你的请求。


struct alignas(64) Test{
    //virtual ~Test(){}
    char arr[9];
    alignas(16) int a;
    double b;
    char c;
};
 
   
问题9) 现在的test对齐值是多少?
要求Test的地址能被64整除,那么Test本初的原始对齐值16,被弃用,使用更大的对齐值64。

问题10) 现在的test大小是多少?
Test的大小是64,增加了更多的填充垃圾字节,以适应64倍数地址值。

问题11) C++11为什么增加这个机制,让程序员控制对齐方式。
1是现有编译器都有语言扩展,例如__declspec(align(n))等,急待统一。
2是现实需求,例如利用placement new语法创建对象,如果你随便提供的内存块同T类型的对齐要求不一致,就是有副作用。
3是语言本身完善的必然,缺了这个东西,C++就不是完备的。C++是如此学院派,价值取向就是相容,独立,完备。





你可能感兴趣的:(学习笔记:alignas用法)