/*
说明:程序是在 centos7 64 位系统下测试的
*/
#include <iostream>
using namespace std;
struct A
{
short var;
int var1;
long var2;
char var3;
string s;
};
int main()
{
short var;
int var1;
long var2;
char var3;
string s;
A ex1;
cout << sizeof(var) << endl; // 2 short
cout << sizeof(var1) << endl; // 4 int
cout << sizeof(var2) << endl; // 8 long
cout << sizeof(var3) << endl; // 1 char
cout << sizeof(s) << endl; // 8 string
cout << sizeof(ex1) << endl; // 32 struct
return 0;
}
输出结果:
[root workspace]#./align
2
4
8
1
8
32
这里对齐怎么搞成了占用 32 个字节呢? 按照 8 字节对齐的话,5*8 = 40 字节 难道第一个 short 和 var1 共同占用 8 个字节? ( short 后面填充两个字节)
1
csfreshman OP 自己顶一下,大佬们都休息了吗
|
2
YePiaoling 2021-05-09 22:34:20 +08:00
是的,可以搜索一下“C++ 内存对齐”
|
3
drizztdu 2021-05-09 22:36:17 +08:00 via iPhone
第一个 short 和 var1 共同占用 8 个字节。把 struct A 的 var2 放到第一位,对其后就占用 24 个字节了。
@csfreshman |
4
billlee 2021-05-09 22:38:11 +08:00
内存对齐基本上可以概括成一个字段的起始地址能被 min {字段大小, 体系字长} 整除
|
5
csfreshman OP @drizztdu 啥意思?把 var2 放第一行有啥区别?还是占 32 个字节吧,我跑了下还是 32 个字节。
|
6
jim9606 2021-05-09 22:44:52 +08:00
var1:0-2
var2:4-8 var3:8-16 var4:16-17 var5:24-32 起始偏移要是成员大小的整数倍。 |
7
irytu 2021-05-09 23:00:12 +08:00 via iPhone
一般结构体里面 考虑对齐的话建议由大到小的顺序摆放 你可以画个图来推演一下 ,对于 struct A 的话( 64bit ):
最小空间:8, 8, 4, 2, 1 = 24 bytes,4 、2 、1 在一个字节里 |
8
irytu 2021-05-09 23:00:31 +08:00 via iPhone
说错了 4 、2 、1 在一个 8 字节里
|
9
hei1000 2021-05-09 23:14:44 +08:00
我的结果是
``` 2 4 8 1 32 56 ``` Manjro-Linux 64-bit, g++ (GCC) 10.2.0 |
10
learningman 2021-05-10 01:27:33 +08:00
2
4 4 1 24 40 VS |
11
geebos 2021-05-10 11:17:50 +08:00
每个类型都有一个对齐值,一般是类型所占内存大小。结构体也有个对齐值,就是结构体成员的对齐值的最大值。
在进行内存对齐的时候要满足以下要求: - 结构体长度要能够整除结构体的对齐值 - 结构体中成员地址到结构体首地址的偏移量要能够整除该成员的对齐值 回到这个问题上来: - short 的长度是 2 字节,所以对齐值也是 2 字节,偏移量为 0,所以不用处理 - int 的长度是 4 字节,但是偏移量是 2 字节(前面成员的所占长度),所以要将偏移量补到( 2+2 ) 4 字节 - long 的长度是 8 字节,偏移量是( 2+2+4 ) 8 字节,可以整除 8,,满足条件 - char 的长度是 1 字节,偏移量是( 2+2+4+8 ) 16 字节,满足条件 - string 的长度是 8 字节,偏移量是( 2+2+4+8+1 ) 17 字节,不满足条件,所以将偏移量补到( 17+7 ) 24 字节 最后总的长度是( 2+2+4+8+1+7+8 ) 32 字节,并且这个长度能够除以结构体的对齐值( 8 ),所以对齐之后的长度就是 32 字节。 |
12
byaiu 2021-05-10 16:25:27 +08:00
#pragma pack(push,1)
struct A { short var; int var1; long var2; char var3; string s; }; #pragma pack(pop) |