求教大佬们一个内存对齐的问题(c++ centos7 64 位系统)

2021-05-09 22:15:31 +08:00
 csfreshman
/*
说明:程序是在 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 后面填充两个字节)

1872 次点击
所在节点    程序员
12 条回复
csfreshman
2021-05-09 22:23:42 +08:00
自己顶一下,大佬们都休息了吗
YePiaoling
2021-05-09 22:34:20 +08:00
是的,可以搜索一下“C++ 内存对齐”
drizztdu
2021-05-09 22:36:17 +08:00
第一个 short 和 var1 共同占用 8 个字节。把 struct A 的 var2 放到第一位,对其后就占用 24 个字节了。
@csfreshman
billlee
2021-05-09 22:38:11 +08:00
内存对齐基本上可以概括成一个字段的起始地址能被 min {字段大小, 体系字长} 整除
csfreshman
2021-05-09 22:43:57 +08:00
@drizztdu 啥意思?把 var2 放第一行有啥区别?还是占 32 个字节吧,我跑了下还是 32 个字节。
jim9606
2021-05-09 22:44:52 +08:00
var1:0-2
var2:4-8
var3:8-16
var4:16-17
var5:24-32
起始偏移要是成员大小的整数倍。
irytu
2021-05-09 23:00:12 +08:00
一般结构体里面 考虑对齐的话建议由大到小的顺序摆放 你可以画个图来推演一下 ,对于 struct A 的话( 64bit ):

最小空间:8, 8, 4, 2, 1 = 24 bytes,4 、2 、1 在一个字节里
irytu
2021-05-09 23:00:31 +08:00
说错了 4 、2 、1 在一个 8 字节里
hei1000
2021-05-09 23:14:44 +08:00
我的结果是
```
2
4
8
1
32
56
```

Manjro-Linux 64-bit, g++ (GCC) 10.2.0
learningman
2021-05-10 01:27:33 +08:00
2
4
4
1
24
40
VS
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 字节。
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)

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/775875

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX