top of page
  • Writer's pictureLingheng Tao

C++ Programming #2 Struct and Union

Updated: Jan 15


这篇笔记主要是关于 C++ 中 struct 结构体和类似的 union 的使用,以及它们各自在内存中的实际占用。这一类的数据结构也被叫做异质的数据结构(Heterogeneous Data Structure)。


Struct


声明


struct 的声明很简单。定义一个名为 StructName 的结构体的语法如下。

struct StructName {
    DataType1 member1;
    DataType2 member2;
    // ...
};

声明一个结构体变量的方式即

StructName myStruct;

在这里,结构体的成员可以包含不同类型的数据成员,例如 int, float, char,或是其他结构体,或数组、指针。


访问结构体的成员需要用操作符(.)。例如,myStruct.member1;


初始化


在声明的时候,就可以初始化

StructName myStruct = {value1, value2};

也可以声明指向结构体的指针。此后,用箭头操作符(->)来访问这个指针所指向的结构体的成员。

StructName myStruct = {value1, value2};
StructName *myStructPtr = &myStruct;
std::cout << (myStructPtr -> member1); // not myStructPtr.member1 !

内存对齐


对于结构体,内存对齐是一个重要的策略,它涉及到如何在内存中安排结构体的成员,以优化访问速度,减少内存空间的浪费。


以下为内存对齐的基本原则:

  1. 结构体的起始地址对齐。例如,如果结构体中最大的成员是 uint32_t,占用 4 字节,那么结构体的起始地址就很可能会在 4 字节的边界上对齐。

  2. 结构体成员对齐。结构体内的每个成员相对于结构体的起始地址通常会对齐到该成员类型自然对齐的边界上。例如,一个 4 字节 int 成员通常在 4 字节边界上对齐。

  3. 结构体总大小对齐。结构体的总大小通常会被填充以对齐到最大成员的对齐边界上。 这意味着结构体的大小可能会比所有成员大小的总和要大。


为了满足上面的对齐基本原则,有的时候编译器会在结构体成员之间或结构体的末尾添加额外的未使用内存,也叫做 Padding (填充)。这种 Memory padding 有助于确保每个成员都在适当的内存地址上。


示例


假设有如下的结构体定义。

struct SomeExample {
	char a; // 1 byte
	int b;  // 4 bytes
	char c; // 1 byte
}

根据对齐规则,这个结构体可能在内存中的布局如下:

  • 内存中最大的成员是 int, 占用 4 字节,因此我们以 4 字节为边界对齐。

  • char a :占用 1 字节。填充 3 字节。

  • int b:占用 4 字节。

  • char c: 占用 1 字节,填充 3 字节。

此时,整个结构体的大小为 12 字节。只要它的起始位置是 4 的倍数,那么它的结束位置之后的那一位也始终会是 4 的倍数。


在结构体中,编译器通常会按照成员的顺序来布局成员,并根据每个成员的对齐要求添加必要的填充。因此,如果我们将结构体声明的顺序进行调整:

struct SomeExample {
	char a; // 1 byte
	char c;  // 1 byte
	int b; // 4 bytes
}

那么,根据内存对齐的规则,这个结构体可能在内存中的布局就会如下:

  • 内存中最大的成员是 int, 占用 4 字节,因此我们以 4 字节为边界对齐。

  • char a :占用 1 字节。不填充。

  • char c:紧随 a 后,占用 1 字节。填充 2 字节。

  • char c: 占用 4 字节,不填充。

此时,整个结构体的大小仅为 8 字节,比之前少了整整 1/3。且依然符合内存对齐的要求。


在一些情况下,程序员可能会因为指针运算的问题去调整对齐策略,有的时候也并非上述第二种情况一定优于第一种情况,因为第一种情况下,我们都按照 int 的大小去调整起始位置就可以去快速获得每一个成员的地址,而第二种情况下我们移动指针的步长有时是 1, 有时是 2, 有时又是 4。最终,要根据项目具体需求来调整结构体的声明。

10 views0 comments

Recent Posts

See All

Comments


bottom of page