一、结构体声明
//声明一个结构体
struct book
{
char title[MAXTITL];//一个字符串表示的titile 题目 ;
char author[MAXAUTL];//一个字符串表示的author作者 ;
float value;//一个浮点型表示的value价格;
};//注意分号不能少,这也相当于一条语句;
1、首先使用关键字struct,它表示接下来是一个结构体;
2、后面是一个可选的标志(book),它是用来引用该结构体的快速标记。
创建结构体:
struct book library;//把library设为一个可以使用book结构体的结构体变量,则library这个变量就包含了其book结构体中的所有元素
二、结构体指针的定义方法
1、struct 结构体名 *指针;
2、直接在定义结构体的时候添加结构体指针的声明。
//结构体的定义
struct student
{
int num;
char name[20];
char sex;
};
struct student *p1;//定义结构体指针
struct student
{
int num;
char name[20];
char sex;
}*p2;//定义结构体指针
三、结构体初始化为{0}的疑惑
在C语言中,结构体可以通过赋值运算符(“=”)进行赋值操作。当将一个结构体赋值为{0}时,表示将结构体的所有成员都设置为0。
假设有如下的结构体定义:
struct MyStruct {
int x;
int y;
char c;
};
然后,我们创建一个该结构体的变量,并将其赋值为{0},如下所示:
struct MyStruct myStruct = {0};
这将会将myStruct
的所有成员都设置为0。在这个例子中,x
和y
会被设置为0,c
会被设置为空字符(‘\0’)。
需要注意的是,这种赋值操作只适用于整数型和字符型成员,对于其他类型的成员(如浮点数、指针等),可能需要使用其他方式进行初始化。
当结构体中包含指针成员时,将结构体赋值为{0}只会将指针成员的值设置为NULL(即空指针)。
例如,考虑以下结构体定义:
struct Person {
char* name;
int age;
};
我们可以通过以下方式将其初始化为{0}:
struct Person person = {0};
这将会将person
的name
成员设置为NULL,age
成员设置为0。
需要注意的是,对于指针成员,只是将指针本身设置为NULL,并没有为指针指向的内存分配空间。如果需要在指针成员中存储实际的数据,需要在赋值之前,为指针分配内存,并将数据存储在该内存中。
例如,可以使用动态内存分配函数malloc
为指针成员分配内存空间,并将数据存储在其中:
struct Person person;
person.name = malloc(20 * sizeof(char)); // 为name指针成员分配20个字符的内存空间
strcpy(person.name, "John"); // 将字符串"John"复制到name指针指向的内存空间中
person.age = 25;
在这种情况下,使用{0}进行赋值初始化无法正确地为指针成员分配内存空间。因此,需要根据具体情况进行适当的内存分配和数据复制操作。
四、结构体的自引用
1、使用typedef时
错误的方式:
typedef struct tag{
int value;
charon *link; /* 虽然也使用指针,但这里的问题是:charon尚未被定义 */
} charon;
这里的目的是使用typedef为结构体创建一个别名charon。但是这里是错误的,因为类型名的作用域是从语句的结尾开始,而在结构体内部是不能使用的,因为还没定义。
当你使用typedef去代替整个结构体并且以原结构体名代替的时候,如果此时你内部还自嵌套了,那么内部的成员变量之前一定要加上struct。
正确的方式:
/* 方法一 */
typedef struct tag_1{
int value;
struct tag_1 *link;
} charon;
/* 方法二 */
struct tag_2; //结构体的不完全声明
typedef struct tag_2 charon;
struct tag_2{
int value;
charon *link;
};
/* 方法三 */
struct tag_3{
int value;
struct tag_3 *link;
};
typedef struct tag_3 charon;
2、不使用typedef时
错误的方式:
struct tag_1
{
struct tag_1 A; /* 结构体 */
int value;
};//这是在无限套
这种声明是错误的,因为这种声明实际上是一个无限循环,成员A是一个结构体,A的内部还会有成员是结构体,依次下去,无线循环。在分配内存的时候,由于无限嵌套,也无法确定这个结构体的长度,所以这种方式是非法的。
正确的方式:
struct tag_1{
struct tag_1 *A; /* 指针 */
int value;
};