自定义结构

枚举

使用#define和const可以创建符号常量,使用enum不仅可以创建符号常量,还能定义新的数据类型。

枚举类型的声明和定义:

1
2
3
4
5
6
7
8
9
10
11
12
13
//声明,创建一个数据类型,还没有分配存储空间
enum wT{
Monday,
Tuseday,
Wednesday,
Thursday,
Firday,
Saturday,
Sunday
};

//定义,创建一个对象
wT weekday;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
using namespace std;
int main()
{
enum wT{Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday}; // 声明wT类型
wT weekday;
weekday = Monday;
weekday = Tuesday;
//weekday = 1; // 错误 不能直接给int值,只能赋值成wT定义好的类型值
//可以写成weekday = wT(1),但是涉及类型转换的写法不推荐
cout << weekday << endl;

//Monday = 0; // 错误 类型值不能做左值,不是有存储空间的变量

int a = Wednesday; //内部有类型转换
cout << a << endl;

return 0;
}

使用细节:

  • 枚举值不能做左值;
  • 非枚举变量不可以赋值给枚举变量;
  • 枚举变量可以赋值给非枚举变量;

结构体和联合体

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//结构体
struct Student
{
char name[6];
int age;
Score s;
};

//联合体
union Score
{
double sc;
char level;
};

存储结构与结构体数据对齐

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <string.h>
#include <iostream>
using namespace std;

int main()
{
union Score
{
double ds; //8字节
char level; //1字节
}; //按照最大值,占用8字节

struct Student
{
char name[6]; //6字节
int age; //32位环境 4字节
Score s; //8字节对齐
}; //整体按照8字节对齐,整体占用24字节

cout << sizeof(Score) << endl; // 8

Student s1;
//注意s1.name=“lili”写法是错误的,编译不过
//数组名不能当左值
strcpy_s(s1.name, "lili");
s1.age = 16;

//联合体占用同一块内存空间
s1.s.ds = 95.5;
s1.s.level = 'A';

cout << sizeof(Student) << endl; // 24


return 0;
}

  联合体内部公用一块内存空间,所以内部占用空间按照最大的数据类型来存储,联合体适合内存受限的场景,比如嵌入式系统。也因为这个原因,同一时间只有一个成员有效,写入一个成员时会覆盖其他成员。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
struct s1
{
char x;
int z;
short y;
};

sizeof(s1) = 12;

struct s2
{
char x;
short y;
int z;
};

sizeof(s2) = 8;

  • 结构体的每个成员在内存中的起始地址必须满足其类型的对其要求,32位系统要求如下:
    • char:任何地址
    • short:偶数倍地址
    • int:4的整数倍、
    • float:4的整数倍
    • double:8的整数倍
    • 指针:4的整数倍

  可以看到,如果结构体中存在一个double,则会按照8字节来对齐。然后所有成员按照顺序依次分配内存,编译器会在成员之间插入填充字节,确保下一个成员满足对齐要求。如果存在结构体嵌套,也按照这个对齐规则,所有结构体中的最大成员值来进行内存对齐。结构体的总大小波许是最大成员对齐值的整数倍。

  程序是可以修改默认编译选项的,修改结构体内存分配,如果设置为1,那就是连续的内存分配布局:

1
2
3
4
5
6
7
Visual C++:
#pragma pack(n)


g++:
__attribute__(aligned(n))
__attribute__(__packed__)