> For the complete documentation index, see [llms.txt](https://legacy.cookielau.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://legacy.cookielau.com/archives/1-cpp/7-keywords.md).

# Key Words

## \_\_attribute\_\_ / packed

### 取消对齐的方法

```cpp
#include<stdio.h>
#pragma pack (1)
struct stu{
    char sex;
    int length;
    char name[10];
};
#pragma pack ()

---------------------------------

struct stu{
    char sex;
    int length;
    char name[10];
}__attribute__ ((packed));

int main(){
    struct stu my_stu;
    printf("%x\n%x\n%x\nsize:%d\n", &(my_stu.sex), &(my_stu.length), &(my_stu.name), sizeof(my_stu));
    return 0;
}
```

上面两种定义 stu 的方式都可以屏蔽编译器的自动对齐，输出结果为:

```bash
e714c971
e714c972
e714c976
size:15
```

不对自动对齐限制的情况下输出结果为：

```bash
e2809960
e2809964
e2809968
size:20
```

可以看出编译器遵循的对齐方法： 1. 首先默认4字节对齐，所以`char sex`占`e2809960-e2809963` 2. 对int占4字节`e2809964-e2809967` 3. 对char型数组占10字节`e2809968-e2809971`

最后对整个结构体进行4字节的对齐，故占据4+4+12=20字节

### 探究默认对齐方式

```cpp
#include <stdio.h>  
void main()  
{  
struct A {  
    int a;  
    char b;  
    short c;  
};  

struct B {  
    char b;  
    int a;  
    short c;  
};  

#pragma pack (2) /*指定按2字节对齐*/  
struct C {  
    char b;  
    int a;  
    short c;  
};  
#pragma pack () /*取消指定对齐，恢复缺省对齐*/  



#pragma pack (1) /*指定按1字节对齐*/  
struct D {  
    char b;  
    int a;  
    short c;  
};  
#pragma pack ()/*取消指定对齐，恢复缺省对齐*/  

int s1=sizeof(struct A);  
int s2=sizeof(struct B);  
int s3=sizeof(struct C);  
int s4=sizeof(struct D);  
printf("%d\n",s1);  
printf("%d\n",s2);  
printf("%d\n",s3);  
printf("%d\n",s4);  
}
```

输出结果：

```
8
12
8
7
```

可以发现int的位置影响了整个结构体的大小，这是因为对齐时，长度为n的类型的其实位置要能被n整除，所以对齐时内部结果如下： ![](https://cdn.jsdelivr.net/gh/CookieLau/imghost/img/20200823171259.png)

### 什么时候需要设置对齐？

在设计不同CPU下的通信协议时，或者编写硬件驱动程序时寄存器的结构这两个地方都需要按**一字节对齐**。即使看起来本来就自然对齐的也要使其对齐，以免不同的编译器生成的代码不一样.

### 字节对齐有什么作用？

* 字节对齐的作用不仅是便于cpu快速访问，同时合理的利用字节对齐可以有效地节省存储空间。
* 对于32位机来说，4字节对齐能够使cpu访问速度提高，比如说一个long类型的变量，如果跨越了4字节边界存储，那么cpu要读取两次，这样效率就低了。但是在32位机中使用1字节或者2字节对齐，反而会使变量访问速度降低。所以这要考虑处理器类型，另外还得考虑编译器的类型。在vc中默认是4字节对齐的，GNU gcc 也是默认4字节对齐。  &#x20;

## static

当变量声明为static时，空间将在程序的生命周期内分配。即使多次调用该函数，静态变量的空间也只分配一次，前一次调用中的变量值通过下一次函数调用传递。这对于在C/C ++或需要存储先前函数状态的任何其他应用程序非常有用。 在cpp文件中，全局变量不加static会在汇编的符号表中加上`.global`，全局可访问；加上`static`可以使得该变量只能在本文件中访问，减小访问的范围，在符号表中类似于`.local`，如：

```cpp
    .text
    .const
__ZStL19piecewise_construct:
    .space 1
    .static_data
__ZStL8__ioinit:
    .space    1
    .globl _gg
    .zerofill __DATA,__pu_bss2,_gg,4,2
    .zerofill __DATA,__bss2,__ZL3lqq,4,2
    .text
    .globl _main
```

其中，变量gg是全局变量不带static，变量lqq是static的全局变量。

## Reference

1. [C++那些事](https://light-city.club/sc/)
2. [csdn | C语言字节对齐 **align(),**&#x61;ttribute((aligned (n))),#pragma pack(n)](https://blog.csdn.net/weixin_40204595/article/details/81134560)
3. [C++ static关键字作用](https://blog.csdn.net/ll148305879/article/details/92794360)
