C基础:05.结构体联合体和枚举以及大小计算

1.结构体的定义和使用

1.1.结构体的定义

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
38
39
40
41
42
// 第一种方式
struct Worker{ // 定义一个结构体, 相当于 java 的 class struct Worker worker; // 初始化,没有初始化的情况下,那么里面所有的属性都是没有初始值的,salary
char name[10];
int age;
double salary;
};*/

// 第二种方式,可以直接取名字
struct Worker{ // 定义一个结构体, 相当于 java 的 class
char name[20];
int age;
double salary;
}eastrise = {"Eastrise",25,1000},jack; // 这种方式会有一个默认的初始值,jack会有默认初始值

struct Work{
char name[10];
char grade[10];
};

// 第三种方式,结构体嵌套
struct Worker{// 定义一个结构体,相当于 java 的 class
char name[10];
int age;
double salary;

// 工作, name grade
Work work;
};

// 第四种方式,结构体嵌套
struct Worker{// 定义一个结构体,相当于 java 的 class
char name[10];
int age;
double salary;

struct Work{
char name[10];
char grade[10];
}work;
// 工作, name grade
// Work work;
};

1.2.结构体的使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
struct Worker{ // 定义一个结构体, 相当于 java 的 class
char name[20];
int age;
double salary;
}eastrise = {"Eastrise",25,1000},jack; // 这种方式会有一个默认的初始值,jack会有默认初始值

// 1. 结构体的定义和使用
// char* 不算基本数据类型
int main(){

struct Worker worker; // 初始化,没有初始化的情况下,那么里面所有的属性都是没有初始值的,salary

// 赋值
worker.age = 24;
// worker.name = "Eastrise";
strcpy(worker.name,"JACK");

// jack.name = "Jack";
strcpy(jack.name,"JACK");
jack.age = 24;

printf("name = %s, age = %d, salary = %lf",eastrise.name,eastrise.age,eastrise.salary);
getchar();
}

打印结果:

1
name = Eastrise, age = 25, salary = 1000.000000

2.结构体指针和动态内存开辟

2.1.通过指针取操作数据

1
2
3
4
5
6
7
8
9
10
11
12
13
int main(){
struct Worker worker = {"eastrise",25};
Worker* worker_p = &worker;

// 通过结构体指针去操控数据
// worker.age = 24;
worker_p -> age = 24; // 结构体操作的另外一种方式, 一般这种比较常用
strcpy(worker_p->name,"Jack");

printf("name = %s, age = %d",worker_p->name,worker_p->age);

getchar();
}

打印结果:

1
name = Jack, age = 24

2.2.动态开辟结构体内存

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
struct Worker{ // 定义一个结构体, 相当于 java 的 class
char name[10];
int age;
double salary;

//工作, name gradle
// Work work;
};

int main(){
// Worker* worker;// 创建了一个结构体指针, 指针没有初始化?
Worker* worker = (Worker*)malloc(sizeof(Worker));
worker->age = 26;
strcpy(worker->name,"Jamin");

printf("name = %s, age = %d",worker->name,worker->age);

// 释放
if(worker){
free(worker);
worker = NULL;
}

getchar();
}

打印结果:

1
name = Jamin, age = 26

结构体的数组

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
struct Worker{ // 定义一个结构体, 相当于 java 的 class
char name[20];
int age;
double salary;
};

// 结构体的数组
int main(){
// 插件结构体数组,第一种
// Worker worker[10] = {{"Eastrise",25,1000},{},{},{}}; // 创建了 10 个,静态开辟
//
// worker[9] = {"Eastrise",26,1000};
//
// printf("name = %s ,age = %d\n",worker[9].name,worker[9].age);

// 动态内存开辟 Worker* 结构体的指针
Worker* worker = (Worker*)malloc(sizeof(Worker)*10);

strcpy(worker->name,"Eastrise");
worker->age = 10;

// 对第十个数据进行操作
worker += 9;
strcpy(worker->name,"Eastrise9");
worker->age = 9;
printf("name = %s,age = %d",worker->name,worker->age);
free(worker);

getchar();
}

打印结果

1
name = Eastrise9,age = 9

3.结构体大小计算(字节对齐)

计算的规则:

  1. 按照最大的字节去计算
  2. 算得时候只会按照基本数据类型去算
  3. 首先会把所有字节数加起来, 是否能够整除最大属性(有其它结构体就按照其它结构体中所有的基本类型数据总和跟本身最大的基本数据类型比较大小)的字节数,如果不够会往上累加,一直加到能整除的位置
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
38
39
40
41
42
43
44
45
46
47
struct Worker{ // 定义一个结构体, 相当于 java 的 class
char name[10]; // 10
int age; // 4
double salary; // 8

// char name[10] 24, char name[18] 32
// 32 怎么来的? 18 + 4 + 8 = 30, 按照能整除最大的基本数据类型来算:32/8=4
};

int main(){
int size = sizeof(Worker); // 24字节
// 计算的规则:
// 1. 按照最大的字节去计算
// 2. 算得时候只会按照基本数据类型去算
// 3. 首先会把所有字节数加起来, 是否能够整除最大属性(有其它结构体就按照其它结构体中所有的基本类型数据总和跟本身最大的基本数据类型比较大小)的字节数,如果不够会往上累加,一直加到能整除的位置

printf("size = %d \n",size);
getchar();
}

struct date{ // 12
int year;
int month;
int day;
};

struct student{
int number; // 4
char sex; // 1
int age; // 4
char name[10]; // 10
struct date birthday; // 12

// 31%4 32%4 32个字节?
};

int main(){
int size = sizeof(student); // 36字节
// 计算的规则:
// 1. 按照最大的字节去计算
// 2. 算得时候只会按照基本数据类型去算
// 3. 首先会把所有字节数加起来, 是否能够整除最大属性(有其它结构体就按照其它结构体中所有的基本类型数据总和跟本身最大的基本数据类型比较大小)的字节数的字节数,如果不够会往上累加,一直加到能整除的位置
// 4. 进阶,留下一个思考

printf("size = %d \n",size);
getchar();
}

打印结果:

1
2
3
24

36

4.结构体和结构体指针取别名

关键词:typedef

typedef Worker_ Worker_; :好处初始化时可以不用带 struct 关键字了

1
2
3
4
5
6
7
8
9
typedef Worker_ Worker_;
// 对结构体的指针取别名
typedef Worker_* Worker;

int main(){
Worker worker = (Worker_*)malloc(sizeof(Worker_));

printf("%s,%d,%lf",worker->name,worker->age,worker->salary);
}

打印结果:

1
,--> 0,---> 0.000000

5.联合体的定义和使用

联合体(共用体) 是一种特殊的数据类型,允许您在相同的内存位置存储不同的数据类型。

联合体因为是在相同的内存位置存储,所以下面代码中只能存在一个,要么是 age ,要么是 name , 后定义的才存在

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
union Person
{
// 最能出现一个 ,不用累加,找最大值 10,12字节
char name[10]; // 10
int age; // 4
double salary;// 8
};

int main(){
// Person person = {"Darren"};
Person person;
strcpy_s(person.name,"Darren");
person.age = 24;
printf("name = %s,age = %d",person.name,person.age); // 只有 age 才有值,因为他是后定义的
printf("%d", sizeof(Person)); // 12
getchar();
}

打印结果:

1
2
name = ,age = 25
16

6. 联合体大小计算

不用累加,取的最大值,最终是否够基本数据类型整除

7.枚举的定义和使用

枚举有点类似于 int,没有指定的依照前面的数值累加

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
enum CommentType
{
// 后面的 = 只能是int类型,否则报错:Integral constant expression must have integral or unscoped enumeration type, not 'const char [4]
TEXT = 10,TEXT_IMAGE =13,IMAGE
};

int main(){

CommentType commentType = TEXT;
CommentType commentType1 = TEXT_IMAGE;
CommentType commentType2 = IMAGE;

printf("%d,%d,%d", commentType, commentType1, commentType2); // 10,13,14

getchar();
}
-------------本文结束感谢您的阅读-------------
坚持原创技术分享,您的支持将鼓励我继续创作!
0%