LV005-结构体简介
我们常见的可以存储很多数据的结构就是数组了,但是它有一个缺点,就是只能存放相同的数据类型。但在实际的问题处理过程中,有许多信息是由多个不同类型的数据组合在一起进行描述的,这些不同类型的数据是互相联系而又组成了一个有机的整体。
例如对于学生信息登记,整体就是整个学校或者整个班级的学生,那每个学生又有姓名,性别,年龄,学号,成绩等不同的属性。姓名为字符串,性别为字符串,年龄为整数,学号为字符串,成绩却又是浮点数,因为数据类型不同,显然不能用一个数组来存放。
这个时候就需要用到一种新的构造类型数据——结构体。
一、结构体简介
1. 怎么定义?
1.1 一般定义格式
定义一个结构体数据类型,我们需要用到 struct 关键字:
struct structure_name
{
data_type member_name1;
data_type member_name2;
...
data_type member_nameN;
};各部分说明如下:
| struct | 结构体定义的关键字,表明这是一个结构体的定义 |
| structure_name | 结构体的名称,与普通变量名要求一样 |
| data_type | 结构体内成员的数据类型,可以是基本变量类型,指针类型,枚举类型,联合体类型或者结构体类型等。比如,char,int 等 |
| member_nameN | 结构体内成员的名称(成员变量名),命名规则与变量相同 |
【注意】
(1)结构体定义结束的时候要有分号( ; )。
(2){ } 内的部分也称为成员列表,或者叫域表。
(3)结构体成员的定义方式与变量和数组的定义方式相同,只是 不能初始化。
(4)结构体类型中的成员名可以与程序中的变量名相同,二者并不代表同一对象,编译程序可以自动对它们进行区分。
(5)它属于 C 语言的一种 数据类型,与整型、实型相当。因此,定义结构体时不分配空间,只有用结构体定义变量时才分配空间。
(6)结构体成员中不允许存在静态变量,即不可以出现 static 。
1.2 定义实例
struct Student
{
char *name; /* 姓名 */
char gender; /* 性别 */
int age; /* 年龄 */
char id[11]; /* 学号 */
float score; /* 成绩 */
}; /* 注意 ; 不可缺少 */Student 为结构体名,它包含了 5 个成员,分别是 name 、gender、age、id、score 。
2. 定义结构体变量
结构体是一种数据类型,在定义完结构体数据类型之后,我们就可以使用该结构体数据类型来定义变量,这样定义的变量就称之为结构体变量。结构体变量定义一般格式如下:
2.1 方式一
- 先定义结构体数据类型,再定义结构体变量
/* 定义结构体数据类型 */
struct Student
{
char *name; /* 姓名 */
char gender; /* 性别 */
int age; /* 年龄 */
char id[11]; /* 学号 */
float score; /* 成绩 */
}; /* ; 不可缺少 */
/* 定义结构体变量 */
struct Student stu1, stu2;上边定义了两个变量 stu1 和 stu2 ,它们都是 Student 结构体类型,都由 5 个成员组成。
【注意】
(1)关键字 struct 不可以省略,若没有这个关键字,则系统不认为 Student 是结构体类型。
(2) Student 就像一个“模板”,定义出来的变量都 具有相同的性质。
(3)程序中使用结构体变量的时候,一般不能把它作为一个整体参与数据的处理,能够参与各种运算符和操作的是结构体变量的各个成员项的数据。
2.2 方式二
- 定义结构体数据类型的同时定义结构体变量
/* 定义结构体数据类型同时定义结构体变量 */
struct Student
{
char *name; /* 姓名 */
char gender; /* 性别 */
int age; /* 年龄 */
char id[11]; /* 学号 */
float score; /* 成绩 */
} stu1, stu2; /* ; 不可缺少 */与方式一类似,定义了两个变量 stu1 和 stu2 ,它们都是 Student 结构体类型,都由 5 个成员组成。如果只需要 stu1 、stu2 两个变量,后面不需要再使用结构体名定义其他变量,那么在定义时也可以不给出结构体名。
/* 定义结构体数据类型同时定义结构体变量 */
struct /* 省略结构体名称 */
{
char *name; /* 姓名 */
char gender; /* 性别 */
int age; /* 年龄 */
char id[11]; /* 学号 */
float score; /* 成绩 */
} stu1, stu2; /* ; 不可缺少 */3. 结构体变量的使用
定义完了结构体变量,接下来就是对结构体变量的使用了,包括了赋值和引用两种操作。
3.1 引用和赋值的格式
结构体变量是一种变量,那么我们自然可以引用变量中的成员,也可以对结构体变量成员进行赋值,这些操作都是通过成员运算符 . 完成的。
- 引用结构体变量成员的方式
结构体变量名.成员名1
结构体变量名.成员名2
...
结构体变量名.成员名N- 对结构体变量成员赋值的方式
结构体变量名.成员名1 = value1;
结构体变量名.成员名2 = value2;
...
结构体变量名.成员名N = valueN;【注意】
(1)不能将结构体变量当做一个整体进行引用,只能对结构体变量的各个成员分别引用。
(2)在引用和赋值的过程中,要注意成员的数据类型,按我自己的理解就是当我们把结构体成员取出来的时候,取出来的这个成员就可以按照普通的变量进行赋值和引用,如果是成员是数组,那么赋值和引用就和普通数组一样。
(3)关于结构体变量的引用就上边的一种格式了,但是对于结构体变量的赋值,却有多种不同的方式。
(4)结构体变量虽然不可以整体引用,但是 相同类型的结构体变量之间允许相互赋值,而 不同类型的结构体变量之间不允许相互赋值,即使两者包含有同样的成员。
3.2 使用实例
#include <stdio.h>
#include <string.h>
/* 定义结构体数据类型 */
struct Student
{
char *name; /* 姓名 */
char gender; /* 性别 */
int age; /* 年龄 */
char id[11]; /* 学号 */
float score; /* 成绩 */
} stu1 = {"qidaink", 'm', 18, "0000000001", 95.8};
int main(int argc, char *argv[])
{
struct Student stu2;
stu2 = stu1;
printf("stu1.name = %s\n", stu1.name);
printf("stu1.gender = %c\n", stu1.gender);
printf("stu1.age = %d\n", stu1.age);
printf("stu1.id = %s\n", stu1.id);
printf("stu1.score = %.2f\n\n", stu1.score);
printf("stu2.name = %s\n", stu2.name);
printf("stu2.gender = %c\n", stu2.gender);
printf("stu2.age = %d\n", stu2.age);
printf("stu2.id = %s\n", stu2.id);
printf("stu2.score = %.2f\n", stu2.score);
return 0;
}在终端执行以下命令:
gcc test.c -Wall # 编译程序
./a.out # 执行可执行文件会看到有如下信息输出:
stu1.name = qidaink
stu1.gender = m
stu1.age = 18
stu1.id = 0000000001
stu1.score = 95.80
stu2.name = qidaink
stu2.gender = m
stu2.age = 18
stu2.id = 0000000001
stu2.score = 95.80二、结构体变量赋值
关于结构体变量的这几种赋值方式,我们都通过实例来进行说明。
1. 赋值方式一
我们可以先定义结构体变量,然后再对各个成员进行赋值。
1.1 一般使用格式
/* 定义结构体数据类型 */
struct STU
{
char *name; /* 姓名 */
char gender; /* 性别 */
int age; /* 年龄 */
char id[11]; /* 学号 */
float score; /* 成绩 */
}; /* ; 不可缺少 */
/* 定义结构体变量 */
struct STU stu1;
/* 对结构体成员逐个进行赋值 */
stu1.name = "qidaink";
stu1.gender = 'm';
stu1.age = 18;
strcpy(stu1.id, "0000000001");
stu1.score = 95.8;1.2 使用实例
/* 头文件 */
#include <stdio.h>
#include <string.h>
/* 定义结构体数据类型 */
struct STU
{
char *name; /* 姓名 */
char gender; /* 性别 */
int age; /* 年龄 */
char id[11]; /* 学号 */
float score; /* 成绩 */
}; /* ; 不可缺少 */
int main(int argc, char *argv[])
{
/* 1.定义结构体变量 */
struct STU stu1;
/* 2.对结构体成员逐个进行赋值 */
stu1.name = "qidaink";
stu1.gender = 'm';
stu1.age = 18;
strcpy(stu1.id, "0000000001");
stu1.score = 95.8;
/* 3.打印各个成员的数据 */
printf("stu1.name = %s\n", stu1.name);
printf("stu1.gender = %c\n", stu1.gender);
printf("stu1.age = %d\n", stu1.age);
printf("stu1.id = %s\n", stu1.id);
printf("stu1.score = %.2f\n", stu1.score);
return 0;
}在终端执行以下命令:
gcc test.c -Wall # 编译链接程序
./a.out # 执行可执行文件会看到有如下信息输出:
stu1.name = qidaink
stu1.gender = m
stu1.age = 18
stu1.id = 0000000001
stu1.score = 95.802. 赋值方式二
我们可以在定义结构体变量的同时进行结构体成员的赋值。
2.1 一般使用格式
/* 定义结构体数据类型 */
struct STU
{
char *name; /* 姓名 */
char gender; /* 性别 */
int age; /* 年龄 */
char id[11]; /* 学号 */
float score; /* 成绩 */
}; /* ; 不可缺少 */
/* 定义结构体变量 */
struct STU stu1 = {"qidaink", 'm', 18, "0000000001", 95.8}; /* 定义结构体变量 */2.2 使用实例
/* 头文件 */
#include <stdio.h>
#include <string.h>
/* 定义结构体数据类型 */
struct STU
{
char *name; /* 姓名 */
char gender; /* 性别 */
int age; /* 年龄 */
char id[11]; /* 学号 */
float score; /* 成绩 */
}; /* ; 不可缺少 */
int main(int argc, char *argv[])
{
/* 1.定义结构体变量 */
struct STU stu1 = {"qidaink", 'm', 18, "0000000001", 95.8}; /* 定义结构体变量 */
/* 2.打印各个成员的数据 */
printf("stu1.name = %s\n", stu1.name);
printf("stu1.gender = %c\n", stu1.gender);
printf("stu1.age = %d\n", stu1.age);
printf("stu1.id = %s\n", stu1.id);
printf("stu1.score = %.2f\n", stu1.score);
return 0;
}在终端执行以下命令:
gcc test.c -Wall # 编译链接程序
./a.out # 执行可执行文件会看到有如下信息输出:
stu1.name = qidaink
stu1.gender = m
stu1.age = 18
stu1.id = 0000000001
stu1.score = 95.803. 赋值方式三
我们可以在定义结构体变量的同时进行结构体成员的 乱序赋值。
3.1 C 风格
3.1.1 基本格式
/* 定义结构体数据类型 */
struct STU
{
char *name; /* 姓名 */
char gender; /* 性别 */
int age; /* 年龄 */
char id[11]; /* 学号 */
float score; /* 成绩 */
}; /* ; 不可缺少 */
/* 定义结构体变量 */
struct STU stu1 =
{
.id = "0000000001",
.gender = 'm',
.name = "qidaink",
.age = 18,
.score = 95.8
}; /* 定义结构体变量 */3.1.2 使用实例
/* 头文件 */
#include <stdio.h>
#include <string.h>
/* 定义结构体数据类型 */
struct STU
{
char *name; /* 姓名 */
char gender; /* 性别 */
int age; /* 年龄 */
char id[11]; /* 学号 */
float score; /* 成绩 */
}; /* ; 不可缺少 */
int main(int argc, char *argv[])
{
/* 1.定义结构体变量 */
struct STU stu1 =
{
.id = "0000000001",
.gender = 'm',
.name = "qidaink",
.age = 18,
.score = 95.8
}; /* 定义结构体变量 */
/* 2.打印各个成员的数据 */
printf("stu1.name = %s\n", stu1.name);
printf("stu1.gender = %c\n", stu1.gender);
printf("stu1.age = %d\n", stu1.age);
printf("stu1.id = %s\n", stu1.id);
printf("stu1.score = %.2f\n", stu1.score);
return 0;
}在终端执行以下命令:
gcc test.c -Wall # 编译链接程序
./a.out # 执行可执行文件会看到有如下信息输出:
stu1.name = qidaink
stu1.gender = m
stu1.age = 18
stu1.id = 0000000001
stu1.score = 95.803.2 C++风格
3.2.1 基本格式
/* 定义结构体数据类型 */
struct STU
{
char *name; /* 姓名 */
char gender; /* 性别 */
int age; /* 年龄 */
char id[11]; /* 学号 */
float score; /* 成绩 */
}; /* ; 不可缺少 */
/* 定义结构体变量 */
struct STU stu1 =
{
id : "0000000001",
gender : 'm',
name : "qidaink",
age : 18,
score : 95.8
};3.2.2 使用实例
/* 头文件 */
#include <stdio.h>
#include <string.h>
/* 定义结构体数据类型 */
struct STU
{
char *name; /* 姓名 */
char gender; /* 性别 */
int age; /* 年龄 */
char id[11]; /* 学号 */
float score; /* 成绩 */
}; /* ; 不可缺少 */
int main(int argc, char *argv[])
{
/* 1.定义结构体变量 */
struct STU stu1 =
{
id : "0000000001",
gender : 'm',
name : "qidaink",
age : 18,
score : 95.8
}; /* 定义结构体变量 */
/* 2.打印各个成员的数据 */
printf("stu1.name = %s\n", stu1.name);
printf("stu1.gender = %c\n", stu1.gender);
printf("stu1.age = %d\n", stu1.age);
printf("stu1.id = %s\n", stu1.id);
printf("stu1.score = %.2f\n", stu1.score);
return 0;
}在终端执行以下命令:
gcc test.c -Wall # 编译链接程序
./a.out # 执行可执行文件会看到有如下信息输出:
stu1.name = qidaink
stu1.gender = m
stu1.age = 18
stu1.id = 0000000001
stu1.score = 95.804. 赋值方式四
我们可以在定义结构体定义结构体时直接定义结构体变量,并直接对结构体变量赋值。
4.1 一般使用格式
/* 定义结构体数据类型 */
struct STU
{
char *name; /* 姓名 */
char gender; /* 性别 */
int age; /* 年龄 */
char id[11]; /* 学号 */
float score; /* 成绩 */
} stu1 = {"qidaink", 'm', 18, "0000000001", 95.8}; /* ; 不可缺少 */4.2 使用实例
/* 头文件 */
#include <stdio.h>
#include <string.h>
/* 定义结构体数据类型 */
struct STU
{
char *name; /* 姓名 */
char gender; /* 性别 */
int age; /* 年龄 */
char id[11]; /* 学号 */
float score; /* 成绩 */
} stu1 = {"qidaink", 'm', 18, "0000000001", 95.8}; /* ; 不可缺少 */
int main(int argc, char *argv[])
{
/* 打印各个成员的数据 */
printf("stu1.name = %s\n", stu1.name);
printf("stu1.gender = %c\n", stu1.gender);
printf("stu1.age = %d\n", stu1.age);
printf("stu1.id = %s\n", stu1.id);
printf("stu1.score = %.2f\n", stu1.score);
return 0;
}在终端执行以下命令:
gcc test.c -Wall # 编译链接程序
./a.out # 执行可执行文件会看到有如下信息输出:
stu1.name = qidaink
stu1.gender = m
stu1.age = 18
stu1.id = 0000000001
stu1.score = 95.805. 结构体变量嵌套赋值
如果说成员本身又属于一个结构体类型,那么我们就需要用若干个成员运算符,一级一级地找到最低一级的成员。只能对最低级的成员进行赋值或存取以及计算。
#include <stdio.h>
#include <string.h>
/* 定义结构体数据类型 */
struct STU
{
char *name; /* 姓名 */
struct
{
int year;
int month;
int day;
} birthday;
}; /* ; 不可缺少 */
int main(int argc, char *argv[])
{
struct STU stu1; /* 定义结构体变量 */
stu1.name = "qidaink";
stu1.birthday.year = 2000;
stu1.birthday.month = 7;
stu1.birthday.day = 7;
printf("stu1.name = %s\n", stu1.name);
printf("stu1.birthday.year = %d\n", stu1.birthday.year);
printf("stu1.birthday.month = %d\n", stu1.birthday.month);
printf("stu1.birthday.day = %d\n", stu1.birthday.day);
return 0;
}在终端执行以下命令:
gcc test.c -Wall # 编译链接程序
./a.out # 执行可执行文件会看到有如下信息输出:
stu1.name = qidaink
stu1.birthday.year = 2000
stu1.birthday.month = 7
stu1.birthday.day = 76. 同类型结构体变量赋值
注意,下面这两种方式,在结构体中包含指针变量的时候,只会对指针变量进行赋值,也就是说,两个结构体变量中的指针变量都将指向同一个地址,这个其实也叫做浅拷贝。数据只有1份,会有两个指针指向这个数据,若是需要深拷贝,需要自行申请内存并拷贝数据。
6.1 赋值运算符赋值
只有 同类型 的结构体变量才能用 = 号来将另一个结构体变量的值赋值给新定义的结构体变量。
/* 头文件 */
#include <stdio.h>
#include <string.h>
/* 定义结构体数据类型 */
struct STU
{
char *name; /* 姓名 */
char gender; /* 性别 */
int age; /* 年龄 */
char id[11]; /* 学号 */
float score; /* 成绩 */
} stu1 = {"qidaink", 'm', 18, "0000000001", 95.8}; /* ; 不可缺少 */
int main(int argc, char *argv[])
{
struct STU stu2 = {0};
/* 打印各个成员的数据 */
printf("stu1.name = %s\n", stu1.name);
printf("stu1.gender = %c\n", stu1.gender);
printf("stu1.age = %d\n", stu1.age);
printf("stu1.id = %s\n", stu1.id);
printf("stu1.score = %.2f\n", stu1.score);
stu2 = stu1;
printf("stu2.name = %s\n", stu2.name);
printf("stu2.gender = %c\n", stu2.gender);
printf("stu2.age = %d\n", stu2.age);
printf("stu2.id = %s\n", stu2.id);
printf("stu2.score = %.2f\n", stu2.score);
return 0;
}将会有以下打印信息:
sumu@virtual-machine:~/hk/alpha$ gcc main.c -Wall
sumu@virtual-machine:~/hk/alpha$ ./a.out
stu1.name = qidaink
stu1.gender = m
stu1.age = 18
stu1.id = 0000000001
stu1.score = 95.80
stu2.name = qidaink
stu2.gender = m
stu2.age = 18
stu2.id = 0000000001
stu2.score = 95.806.2 memcpy 赋值
只有 同类型 的结构体变量才能用memcpy来将另一个结构体的值拷贝到新定义的结构体中。
/* 头文件 */
#include <stdio.h>
#include <string.h>
/* 定义结构体数据类型 */
struct STU
{
char *name; /* 姓名 */
char gender; /* 性别 */
int age; /* 年龄 */
char id[11]; /* 学号 */
float score; /* 成绩 */
} stu1 = {"qidaink", 'm', 18, "0000000001", 95.8}; /* ; 不可缺少 */
int main(int argc, char *argv[])
{
struct STU stu2 = {0};
/* 打印各个成员的数据 */
printf("stu1.name = %s\n", stu1.name);
printf("stu1.gender = %c\n", stu1.gender);
printf("stu1.age = %d\n", stu1.age);
printf("stu1.id = %s\n", stu1.id);
printf("stu1.score = %.2f\n", stu1.score);
memcpy(&stu2, &stu1, sizeof(struct STU));
printf("stu2.name = %s\n", stu2.name);
printf("stu2.gender = %c\n", stu2.gender);
printf("stu2.age = %d\n", stu2.age);
printf("stu2.id = %s\n", stu2.id);
printf("stu2.score = %.2f\n", stu2.score);
return 0;
}将会有以下打印信息:
sumu@virtual-machine:~/hk/alpha$ gcc main.c -Wall
sumu@virtual-machine:~/hk/alpha$ ./a.out
stu1.name = qidaink
stu1.gender = m
stu1.age = 18
stu1.id = 0000000001
stu1.score = 95.80
stu2.name = qidaink
stu2.gender = m
stu2.age = 18
stu2.id = 0000000001
stu2.score = 95.80三、结构体的长度
1. 计算格式
当我们定义了一个结构体后,用它定义出来的结构体变量占多大空间呢?我们可以使用 sizeof 函数来求得所定义结构体的长度。一般格式如下:
sizeof(struct structure_name)
/* 或者使用结构体变量来求 */
struct structure_name structure_variable;
sizeof(structure_variable)2. 使用实例
#include <stdio.h>
/* 定义结构体数据类型 */
struct STU
{
char *name; /* 姓名 */
char gender; /* 性别 */
int age; /* 年龄 */
char id[3]; /* 学号 */
float score; /* 成绩 */
}; /* ; 不可缺少 */
int main(int argc, char *argv[])
{
struct STU stu1 = {"qidaink", 'm', 18, "01", 95.8}; /* 定义结构体变量 */
printf("sizeof(stu1) = %ld\n", sizeof(stu1));
printf("sizeof( struct Student) = %ld\n", sizeof(struct STU));
printf("sizeof(stu1.name) = %ld\n", sizeof(stu1.name));
printf("sizeof(stu1.gender) = %ld\n", sizeof(stu1.gender));
printf("sizeof(stu1.age) = %ld\n", sizeof(stu1.age));
printf("sizeof(stu1.id) = %ld\n", sizeof(stu1.id));
printf("sizeof(stu1.score) = %.ld\n\n", sizeof(stu1.score));
return 0;
}在终端执行以下命令:
gcc test.c -Wall # 编译链接程序
./a.out # 执行可执行文件会看到有如下信息输出:
sizeof(stu1) = 24
sizeof( struct Student) = 24
sizeof(stu1.name) = 8
sizeof(stu1.gender) = 1
sizeof(stu1.age) = 4
sizeof(stu1.id) = 3
sizeof(stu1.score) = 464 位平台下的指针变量固定为 8 字节。我们会发现,总的大小并非是各个成员所占空间大小的总和,那我们就接着往后看。
四、在内存中的存储
当结构体定义了一个结构体变量的时候,这个结构体变量在内存中是怎样的呢?
1. 一个实例
结构体在定义的时候并不分配内存空间,所以无法对结构体名称进行取地址操作,但是当用它定义了结构体变量之后,就可以使用 & 符号来获取结构体变量在内存中的起始地址了。
#include <stdio.h>
/* 定义结构体数据类型 */
struct STU
{
char *name; /* 姓名 */
char gender; /* 性别 */
int age; /* 年龄 */
char id[3]; /* 学号 */
float score; /* 成绩 */
}; /* ; 不可缺少 */
int main(int argc, char *argv[])
{
struct STU stu1 = {"qidaink", 'm', 18, "01", 95.8}; /* 定义结构体变量 */
printf("sizeof( struct STU) = %ld\n", sizeof(struct STU));
printf("&stu1 = %p,sizeof(stu1) = %ld\n", &stu1, sizeof(stu1));
printf("&stu1.name = %p,sizeof(stu1.name) = %ld\n", &stu1.name, sizeof(stu1.name));
printf("&stu1.gender = %p,sizeof(stu1.gender) = %ld\n", &stu1.gender, sizeof(stu1.gender));
printf("&stu1.age = %p,sizeof(stu1.age) = %ld\n", &stu1.age, sizeof(stu1.age));
printf("&stu1.id = %p,sizeof(stu1.id) = %ld\n", &stu1.id, sizeof(stu1.id));
printf("&stu1.id[0] = %p,sizeof(stu1.id[0]) = %ld\n", &stu1.id[0], sizeof(stu1.id[0]));
printf("&stu1.id[1] = %p,sizeof(stu1.id[1]) = %ld\n", &stu1.id[1], sizeof(stu1.id[1]));
printf("&stu1.id[2] = %p,sizeof(stu1.id[2]) = %ld\n", &stu1.id[2], sizeof(stu1.id[2]));
printf("&stu1.score = %p,sizeof(stu1.score) = %.ld\n\n", &stu1.score, sizeof(stu1.score));
return 0;
}在终端执行以下命令:
gcc test.c -Wall # 编译链接程序
./a.out # 执行可执行文件会看到有如下信息输出:
sizeof( struct Student) = 24
&stu1 = 0x7fff1635a610,sizeof(stu1) = 24
&stu1.name = 0x7fff1635a610,sizeof(stu1.name) = 8
&stu1.gender = 0x7fff1635a618,sizeof(stu1.gender) = 1
&stu1.age = 0x7fff1635a61c,sizeof(stu1.age) = 4
&stu1.id = 0x7fff1635a620,sizeof(stu1.id) = 3
&stu1.id[0] = 0x7fff1635a620,sizeof(stu1.id[0]) = 1
&stu1.id[1] = 0x7fff1635a621,sizeof(stu1.id[1]) = 1
&stu1.id[2] = 0x7fff1635a622,sizeof(stu1.id[2]) = 1
&stu1.score = 0x7fff1635a624,sizeof(stu1.score) = 4Tips:64 位平台下的指针变量固定为 8 字节。
2. 内存分布
我们画个图来帮助理解:

从最终例子中打印的数据分析, gender 是一个 char 类型的数据,只占用了 1 个字节的数据,但是它后边空出来了 3 个字节数据。数组 id 也是,总长度是 3 字节,"空" 出了 1 个字节空间。这样算下来,总长度就是 8+4+4+8 = 24 了,这也就对应上了。但是,这些 "空" 出来的空间是为什么呢?这就涉及到了字节对齐,可以看后面的 《结构体大小.md》。