• c++11~c++20 -06-字节对齐alignof、alignas


    前言

    C++11中新增加了alignof和alignas两个关键字,其中alignof运算符可以用于获取类型的对齐字节长度,alignas说明符可以用来改变类型的默认对齐字节长度。

    接下来先看看下面这段代码:

    #include
    using namespace std;
    
    struct A
    {
    	char   a1;
    	int    a2;
    	double a3;
    };
    
    struct B
    {
    	short  b1;
    	bool   b2;
    	double a3;
    };
    
    
    int main()
    {
    
    	cout << "sizeof(A) = " << sizeof(A) << endl;
    	cout << "sizeof(B) = " << sizeof(B) << endl;
    		
    	system("pause");
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    结果:
    在这里插入图片描述
    奇怪的事情是A的成员变量的大小应该为 1+4+8 = 13,B的成员变量大小应该为:2+1+8 = 11.但是他们本身的数据长度却为16.有经验的程序员因该一眼就能看出其中的原因,实际上一个类型的属性除了其数据长度,还有一个重要的属性–数据对齐的字节长度。下面给出A的内存布局示意图
    在这里插入图片描述
    那这里肯定有人会有疑问:为什么要内存对齐呢?其实原因很简单,就是硬件需要。一个好的对齐字节长度可以让CPU运行起来更加轻松快速,反过来说,不好的对齐字节长度会让CPU运行速度减慢。通常来说所谓好的对齐长度和CPU访问数据总线的宽度有关系,比如CPU访问32位宽度的数据总线,就会期待数据按照32位对齐,也就是4字节,这样CPU读取4字节的数据只需要访问一次.

    使用alignof运算符

    添加如下的代码:

    struct C
    {
    	short  b1;
    	bool   b2;
    };
    
    int main()
    {
    
    	cout << alignof(int) << endl;
    	cout << alignof(double) << endl;
    
    	cout << alignof(A) << endl;
    	cout << alignof(B) << endl;
    	cout << alignof(C) << endl;
    		
    	system("pause");
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    结果:
    在这里插入图片描述

    C++11之前内存对齐方式

    #pragma pack(2)   /*指定按2字节对齐  ~start*/    
    struct A
    {
    	char   a1;
    	int    a2;
    	double a3;
    };
    
    #pragma  pack() //*取消指定对齐,恢复缺省对齐 ~ end */
    
    int main()
    {
    
    	cout << alignof(A) << endl;
    	cout <<"sizeof(A) = "<< sizeof(A) << endl;
    	system("pause");
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    结果:
    在这里插入图片描述
    不字节对齐的话 就设置#pragma pack(1)

    #pragma pack(1)   /*指定按2字节对齐  ~start*/    
    struct A
    {
    	char   a1;
    	int    a2;
    	double a3;
    };
    
    #pragma  pack() //*取消指定对齐,恢复缺省对齐 ~ end */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    结果:
    在这里插入图片描述

    使用alignas

    alignas一般在类型定义时,放在名称前,可以接受常量表达式和类型作为参数,可以修饰变量、类的数据成员等,不能修饰位域和用register申明的变量。一般往大对齐。

    直接看一段代码(结合上一段代码):

    struct alignas(4) A
    {
    	char   a1;	
    };
    
    
    struct alignas(32) B
    {
    	short  b1;
    	bool   b2;
    	double a3;
    };
    
    
    struct alignas(8) C
    {
    	short  b1;
    	bool   b2;
    };
    
    int main()
    {
    
    	cout <<"alignof(A) = "<< alignof(A) << endl;
    	cout <<"sizeof(A) = "<< sizeof(A) << endl;
    
    	cout << "alignof(B) = " << alignof(B) << endl;
    	cout << "sizeof(B) = " << sizeof(B) << endl;
    
    	cout << "alignof(C) = " << alignof(C) << endl;
    	cout << "sizeof(C) = " << sizeof(C) << endl;
    	system("pause");
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    结果:
    在这里插入图片描述

  • 相关阅读:
    vue 甘特图(三):甘特图右侧内容拖动展示
    Nginx默认会自动忽略请求头Headers里带下划线_的参数
    Ubuntu 20.04编译Chrome浏览器
    IDM的实用功能
    vue的$nextTick是什么是干什么用的?
    TLSR8258应用笔记
    【期末大作业】基于HTML+CSS+JavaScript网上订餐系统(23个页面)
    Win11最新KB5019980(22621.819)更新内容详解
    【论文精读】【DETR】End-to-End Object Detection with Transformers
    C++入门——引用|内联函数|auto关键字|基于范围的for循环|指针空值
  • 原文地址:https://blog.csdn.net/FairLikeSnow/article/details/126313237