golang 和 C++的內存對齊,基本一致,記住規則和對應類型的 size 即可
內存對齊規則
- 有效對齊值是固定值和結構體中最長數據類型長度中較小的那個。固定值系統默認為 32 位是 4, 64 位是 8,
#pragma pack(n)
設置了則是對應的 n。 - 結構體第一個成員的 offset 為 0,以后每個成員相對于結構體首地址的 offset 都是
min{該成員大小, 有效對齊值}
的整數倍,如有需要編譯器會在成員之間加上填充字節。 - 結構體的總大小為 有效對齊值 的整數倍,如有需要編譯器會在最末一個成員之后加上填充字節。
C++內存對齊
常見類型占用內存大小
類型/編譯器 | 16 位編譯器 | 32 位編譯器 | 64 位編譯器 |
---|---|---|---|
bool | 1 | 1 | 1 |
char | 1 | 1 | 1 |
char* | 2 | 4 | 8 |
int | 2 | 4 | 4 |
float | 4 | 4 | 4 |
double | 8 | 8 | 8 |
long long | 8 | 8 | 8 |
例子
#include <iostream>
#include <stdint.h>
using namespace std;
// #pragma pack(4)
class Part1 {
bool a;
int32_t b;
int8_t c;
int64_t d;
char e;
};
class Part2 {
char e;
int8_t c;
bool a;
int32_t b;
int64_t d;
};
int main(void){
Part1 part1;
Part2 part2;
printf("part1 size: %zu\n", sizeof(part1));
printf("part2 size: %zu\n", sizeof(part2));
}
// output:
// part1 size: 32, if pack(4): part1 size: 24
// part2 size: 16
golang 內存對齊
常見類型占用內存大小
類型/編譯器 | 64 位編譯器 |
---|---|
bool | 1 |
byte | 1 |
uintptr | 8 |
int | 8 |
float64 | 8 |
string | 16 |
例子
package main
import (
"fmt"
"unsafe"
)
type Part1 struct {
a bool
b int32
c int8
d int64
e byte
}
type Part2 struct {
e byte
c int8
a bool
b int32
d int64
}
func main() {
part1 := Part1{}
part2 := Part2{}
fmt.Printf("part1 size: %d, align: %d\n", unsafe.Sizeof(part1), unsafe.Alignof(part1))
fmt.Printf("part2 size: %d, align: %d\n", unsafe.Sizeof(part2), unsafe.Alignof(part2))
}
// part1 size: 32, align: 8
// part2 size: 16, align: 8
例子分析
僅討對齊固定值為 8 時 Part1 的情況,例子中的 a,b,c,d,e 占用大小分別為 1,4,1,8,1。填充字節用 0 表示,|之間表示 8 字節空間:
- a 偏移為 0,|a...
- b 偏移為 4 的整數倍,|a000b|...
- c 偏移為 1 的整數倍,|a000b|c...
- d 偏移為 8 的整數倍,|a000b|c0000000|d|...
- e 偏移為 1 的整數倍,|a000b|c0000000|d|e...
- 整個結構體對齊,補齊為 8 的整數倍,|a000b|c0000000|d|e0000000|
- 得出總大小為 32