C语言的结构体是一种自定义的 数据类型,它允许你将不同类型的数据组合在一起,形成一个新的数据类型,以便更方便地管理和操作这些数据。结构体可以包含多个成员(也称为字段或属性),每个成员可以是不同的数据类型,例如整数、浮点数、字符、数组或其他结构体。
简单声明一个结构体如下:结构体名称是你给这个结构体类型取的标识符,可以根据需要自行命名。
struct 结构体名称 {
数据类型 成员1;
数据类型 成员2;
// 其他成员定义...
};
结构体类型:结构体类型是用户自定义的数据类型,用于表示一组相关的数据,这些数据可以是不同的类型。(也就是结构体的定义)
结构体变量:也就是结构体类型变量,它是根据结构体类型创建的具体实例,用于存储实际的数据。
struct Student {
char name[50];
int age;
float gpa;
};
这里就是创建了一个名为Student的结构体类型。
struct Student student1;
struct Student student2;
这里就是创建了个名为student1和student2的两个结构体变量。
第一种声明方式:
struct point{
int x;
int y;
};
struct point pl;
struct point p2;
结构体类型的名字叫point,结构体变量的名字p1和p2。在这里声明结构体变量的时候必须加上struct ,struct point这两个合起来才代表point这种结构类型。
第二种声明方式:
struct {
int x;
int y;
} pl,p2;
这里没有定义结构体类型的名字,结构体变量的名字p1和p2。这里已经声明了两个结构体变量了,不需要再单独声明了。
第三种声明方式:
struct point{
int x;
int y;
} pl,p2;
结构体类型的名字叫point,结构体变量的名字p1和p2。这里已经声明了两个结构体变量了,不需要再单独声明了。
第四种声明方式:(自定义数据类型)
在C语言中,typedef是一个用于创建自定义数据类型别名的关键字。具体使用如下:
typedef struct point{
int x;
int y;
} p;
//或者
typedef struct {
int x;
int y;
} p;
//声明结构体变量
p p1;
p p2;
上面两种声明中,一种的结构体类型名是point,另一种是无名结构体类型,最后新的结构体类型名都变成了p;这里和上面的不同的是p是新的结构体类型名字,而不是结构体变量名;声明结构体变量还是要通过p p1;这样声明,这样使用typedef的好处是声明结构体变量时,不用再加上struct了。
// 定义结构体类型
typedef struct {
int x;
int y;
int z;
} p;
常用方法1:
对结构体成员进行初始化,这里的初始化的顺序必须与结构体成员定义的顺序一致。
p p1 = {1,2,3};
常用方法2:
通过成员名来指定结构体成员的初始化。
// 定义结构体类型
struct Person {
char name[50];
int age;
float height;
float gpa;
};
struct Person person1 = {
.name = "John Doe",
.age = 25,
.height = 175.5,
.gpa = 85.5
};
struct Person person1 = {
.name = "John Doe",
.age = 25,
.height = 175.5, //这里没有初始化gpa,其值会默认为0
};
上面初始化的过程中,通过.的操作来取结构体成员进行相应的初始化,如果初始化的个数少于原本结构体的成员个数,那么系统会把未初始化的成员赋值为0。
概念:结构体指针是指针变量,用于存储和操作结构体类型的地址。通过结构体指针,你可以访问结构体的成员,动态创建结构体实例,以及在函数中传递结构体的引用,避免复制结构体数据。
//声明一个结构体
struct Person {
char name[50];
int age;
float height;
};
//创建一个结构体变量
struct Person person1;
// 声明指向结构体的指针,并将其指向结构体实例
struct Person *p = &person1;
通过指针访问结构体中的成员:
p->age = 25; //通过指针访问结构体中的成员,注意person1没有person1->age,因为person1不是指针,没有->操作
person1.age = 25; //通过结构体变量访问结构体中的成员
这里的(*p)就代表结构体变量。
(*p).age = 25;
person1.age = 25;
举一个简单实例:
#include
struct Person {
char name[50];
int age;
float height;
};
int main() {
// 创建结构体实例
struct Person person1 = {"John Doe", 25, 175.5};
// 声明指向结构体的指针,并将其指向结构体实例
struct Person *personPtr = &person1;
// 通过指针访问结构体成员
printf("Name: %s\n", personPtr->name);
printf("Age: %d\n", personPtr->age);
printf("Height: %.2f\n", personPtr->height);
return 0;
}
结构体嵌套是指在一个结构体中包含另一个结构体作为其成员。这种嵌套的结构体允许将多个相关的数据组合在一起,形成更复杂的数据结构。举例如下:
struct point{
int x;
int y;
};
struct rectangle{
struct point p1; //p1是一个结构体变量
struct point p2; //p2是一个结构体变量
};
//初始化一个rectangle实例
struct rectangle r1 = {
{3,1},
{4,2},
};
//访问成员变量,按照顺序进行
r1.p1.x = 3;
//初始化一个结构体数组
struct rectangle r2[2] = {
{{3,1},{4,2}},
{{5,3},{6,4}},
};
//访问成员变量,按照顺序进行
r2[1].p1.x = 3;
共用体(Union)是一种特殊的数据类型,允许在相同的内存空间中存储不同类型的数据。共用体的内存空间大小等于其最大成员的大小,因为共用体中的所有成员共用同一块内存。
共用体的一个典型应用是在需要在不同数据类型之间进行转换或共享相同内存的情况下。注意,由于共用体的不同成员共用同一块内存,只能同时存储其中一个成员的值。举例如下:
#include
#include
// 定义共用体
union Data {
int intValue; //int类型变量
char ch[sizeof(int)]; //字符数组 在x86的32位或者64位里面,sizeof(int) = 4
};
int main() {
union Data data; //声明共用体变量
data.intValue = 1234; //给变量成员赋值
printf("Value as integer: %d\n", data.intValue);
for(int i = 0; i < sizeof(int); i++){
printf("%02hhX\r\n",data.ch[i]); //观察数组中存放的数据(因为共用了一块内存地址)
}
return 0;
}
**这里1234的16进制表示是04D2,所以数组四个元素应该是00,00,04,D2的组合,**但是大多数计算机都采用小端存储,即低位字节(即较低地址)保存在内存中的低地址,高位字节(即较高地址)保存在内存中的高地址。04是高字节所以要存在高地址上,就在D2后面。
在printf语句中:
02: 表示输出的十六进制数占据两个字符宽度,如果不足两位,则在前面填充0;
hh: 表示参数 ch[i] 是一个 char 类型,将其按无符号字符类型输出。
X: 表示以大写字母的十六进制形式输出。
上面程序运行的结果如下: