Skip to content

LV005-结构体简介

我们常见的可以存储很多数据的结构就是数组了,但是它有一个缺点,就是只能存放相同的数据类型。但在实际的问题处理过程中,有许多信息是由多个不同类型的数据组合在一起进行描述的,这些不同类型的数据是互相联系而又组成了一个有机的整体。

例如对于学生信息登记,整体就是整个学校或者整个班级的学生,那每个学生又有姓名,性别,年龄,学号,成绩等不同的属性。姓名为字符串,性别为字符串,年龄为整数,学号为字符串,成绩却又是浮点数,因为数据类型不同,显然不能用一个数组来存放。

这个时候就需要用到一种新的构造类型数据——结构体。

一、结构体简介

1. 怎么定义?

1.1 一般定义格式

定义一个结构体数据类型,我们需要用到 struct 关键字:

c
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 定义实例

c
struct Student
{
	char *name;      /* 姓名 */
	char gender;     /* 性别 */
	int age;         /* 年龄 */
	char id[11];     /* 学号 */
	float score;     /* 成绩 */
};                   /* 注意 ; 不可缺少 */

Student 为结构体名,它包含了 5 个成员,分别是 name 、gender、age、id、score 。

2. 定义结构体变量

结构体是一种数据类型,在定义完结构体数据类型之后,我们就可以使用该结构体数据类型来定义变量,这样定义的变量就称之为结构体变量。结构体变量定义一般格式如下:

2.1 方式一

  • 先定义结构体数据类型,再定义结构体变量
c
/* 定义结构体数据类型 */
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 方式二

  • 定义结构体数据类型的同时定义结构体变量
c
/* 定义结构体数据类型同时定义结构体变量 */
struct Student
{
	char *name;      /* 姓名 */
	char gender;     /* 性别 */
	int age;         /* 年龄 */
	char id[11];     /* 学号 */
	float score;     /* 成绩 */
} stu1, stu2;        /* ; 不可缺少 */

与方式一类似,定义了两个变量 stu1 和 stu2 ,它们都是 Student 结构体类型,都由 5 个成员组成。如果只需要 stu1 、stu2 两个变量,后面不需要再使用结构体名定义其他变量,那么在定义时也可以不给出结构体名

c
/* 定义结构体数据类型同时定义结构体变量 */
struct               /* 省略结构体名称 */
{
	char *name;      /* 姓名 */
	char gender;     /* 性别 */
	int age;         /* 年龄 */
	char id[11];     /* 学号 */
	float score;     /* 成绩 */
} stu1, stu2;        /* ; 不可缺少 */

3. 结构体变量的使用

定义完了结构体变量,接下来就是对结构体变量的使用了,包括了赋值和引用两种操作。

3.1 引用和赋值的格式

结构体变量是一种变量,那么我们自然可以引用变量中的成员,也可以对结构体变量成员进行赋值,这些操作都是通过成员运算符 . 完成的。

  • 引用结构体变量成员的方式
c
结构体变量名.成员名1
结构体变量名.成员名2
...
结构体变量名.成员名N
  • 对结构体变量成员赋值的方式
c
结构体变量名.成员名1 = value1;
结构体变量名.成员名2 = value2;
...
结构体变量名.成员名N = valueN;

注意

(1)不能将结构体变量当做一个整体进行引用,只能对结构体变量的各个成员分别引用。

(2)在引用和赋值的过程中,要注意成员的数据类型,按我自己的理解就是当我们把结构体成员取出来的时候,取出来的这个成员就可以按照普通的变量进行赋值和引用,如果是成员是数组,那么赋值和引用就和普通数组一样。

(3)关于结构体变量的引用就上边的一种格式了,但是对于结构体变量的赋值,却有多种不同的方式。

(4)结构体变量虽然不可以整体引用,但是 相同类型的结构体变量之间允许相互赋值,而 不同类型的结构体变量之间不允许相互赋值,即使两者包含有同样的成员。

3.2 使用实例

c
#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;
}

在终端执行以下命令:

shell
gcc test.c -Wall # 编译程序 
./a.out          # 执行可执行文件

会看到有如下信息输出:

shell
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 一般使用格式

c
/* 定义结构体数据类型 */
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 使用实例

c
/* 头文件 */
#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;
}

在终端执行以下命令:

shell
gcc test.c -Wall # 编译链接程序 
./a.out          # 执行可执行文件

会看到有如下信息输出:

shell
stu1.name = qidaink
stu1.gender = m
stu1.age = 18
stu1.id = 0000000001
stu1.score = 95.80

2. 赋值方式二

我们可以在定义结构体变量的同时进行结构体成员的赋值。

2.1 一般使用格式

c
/* 定义结构体数据类型 */
struct STU
{
	char  *name;      /* 姓名 */
	char  gender;     /* 性别 */
	int   age;        /* 年龄 */
	char  id[11];     /* 学号 */
	float score;      /* 成绩 */
};                    /* ; 不可缺少 */

/* 定义结构体变量 */
struct STU stu1 = {"qidaink", 'm', 18, "0000000001", 95.8}; /* 定义结构体变量 */

2.2 使用实例

c
/* 头文件 */
#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;
}

在终端执行以下命令:

shell
gcc test.c -Wall # 编译链接程序 
./a.out          # 执行可执行文件

会看到有如下信息输出:

shell
stu1.name = qidaink
stu1.gender = m
stu1.age = 18
stu1.id = 0000000001
stu1.score = 95.80

3. 赋值方式三

我们可以在定义结构体变量的同时进行结构体成员的 乱序赋值

3.1 C 风格

3.1.1 基本格式
c
/* 定义结构体数据类型 */
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 使用实例
c
/* 头文件 */
#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;
}

在终端执行以下命令:

shell
gcc test.c -Wall # 编译链接程序 
./a.out          # 执行可执行文件

会看到有如下信息输出:

shell
stu1.name = qidaink
stu1.gender = m
stu1.age = 18
stu1.id = 0000000001
stu1.score = 95.80

3.2 C++风格

3.2.1 基本格式
c
/* 定义结构体数据类型 */
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 使用实例
c
/* 头文件 */
#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;
}

在终端执行以下命令:

shell
gcc test.c -Wall # 编译链接程序 
./a.out          # 执行可执行文件

会看到有如下信息输出:

shell
stu1.name = qidaink
stu1.gender = m
stu1.age = 18
stu1.id = 0000000001
stu1.score = 95.80

4. 赋值方式四

我们可以在定义结构体定义结构体时直接定义结构体变量,并直接对结构体变量赋值。

4.1 一般使用格式

c
/* 定义结构体数据类型 */
struct STU
{
	char  *name;      /* 姓名 */
	char  gender;     /* 性别 */
	int   age;        /* 年龄 */
	char  id[11];     /* 学号 */
	float score;      /* 成绩 */
} stu1 = {"qidaink", 'm', 18, "0000000001", 95.8}; /* ; 不可缺少 */

4.2 使用实例

c
/* 头文件 */
#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;
}

在终端执行以下命令:

shell
gcc test.c -Wall # 编译链接程序 
./a.out          # 执行可执行文件

会看到有如下信息输出:

shell
stu1.name = qidaink
stu1.gender = m
stu1.age = 18
stu1.id = 0000000001
stu1.score = 95.80

5. 结构体变量嵌套赋值

如果说成员本身又属于一个结构体类型,那么我们就需要用若干个成员运算符,一级一级地找到最低一级的成员。只能对最低级的成员进行赋值或存取以及计算。

c
#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;
}

在终端执行以下命令:

shell
gcc test.c -Wall # 编译链接程序 
./a.out          # 执行可执行文件

会看到有如下信息输出:

shell
stu1.name = qidaink
stu1.birthday.year = 2000
stu1.birthday.month = 7
stu1.birthday.day = 7

6. 同类型结构体变量赋值

注意,下面这两种方式,在结构体中包含指针变量的时候,只会对指针变量进行赋值,也就是说,两个结构体变量中的指针变量都将指向同一个地址,这个其实也叫做浅拷贝。数据只有1份,会有两个指针指向这个数据,若是需要深拷贝,需要自行申请内存并拷贝数据。

6.1 赋值运算符赋值

只有 同类型 的结构体变量才能用 = 号来将另一个结构体变量的值赋值给新定义的结构体变量。

c
/* 头文件 */
#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;
}

将会有以下打印信息:

shell
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

6.2 memcpy 赋值

只有 同类型 的结构体变量才能用memcpy来将另一个结构体的值拷贝到新定义的结构体中。

c
/* 头文件 */
#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;
}

将会有以下打印信息:

shell
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 函数来求得所定义结构体的长度。一般格式如下:

c
sizeof(struct structure_name) 
/* 或者使用结构体变量来求 */
struct structure_name structure_variable;
sizeof(structure_variable)

2. 使用实例

c
#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;
}

在终端执行以下命令:

shell
gcc test.c -Wall # 编译链接程序 
./a.out          # 执行可执行文件

会看到有如下信息输出:

shell
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) = 4

64 位平台下的指针变量固定为 8 字节。我们会发现,总的大小并非是各个成员所占空间大小的总和,那我们就接着往后看。

四、在内存中的存储

当结构体定义了一个结构体变量的时候,这个结构体变量在内存中是怎样的呢?

1. 一个实例

结构体在定义的时候并不分配内存空间,所以无法对结构体名称进行取地址操作,但是当用它定义了结构体变量之后,就可以使用 & 符号来获取结构体变量在内存中的起始地址了。

c
#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;
}

在终端执行以下命令:

shell
gcc test.c -Wall # 编译链接程序 
./a.out          # 执行可执行文件

会看到有如下信息输出:

shell
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) = 4

Tips:64 位平台下的指针变量固定为 8 字节。

2. 内存分布

我们画个图来帮助理解:

image-20260303152844605

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