目录
- 前言
- 标签
- typedef
- 结构体的自引用
- 方法一
- 方法二
前言
在C语言中,常常使用数组存储若干个同种类型的数据,若想存储不同类型的数据,就要用到结构体了,结构体是一些值的集合,这些值称为它的成员,下面叙述声明结构体的误区:
1、struct{
int a;
char b;
}ss;
2、struct{
int a;
char b;
}st;
声明1创建了一个名为ss的变量,声明2创建了一个名为st的变量,它们都包含两个成员:int型的a和char型的b。需要注意,虽然ss和st的成员完全相同,但是这样声明会被编译器处理为两种不同的数据类型,不能相互赋值,示例如下:
#include <stdio.h>
struct {
int a;
char b;
}st;
struct
{
int a;
char b;
}ss;
int main(void)
{
scanf("%d %c", &ss.a, &ss.b);
printf("ss的值分别为:%d %c\n", ss.a, ss.b);
st = ss;
return 0;
}
会报如下类型不匹配的错误:
标签
如果想创建同一种类型的结构体变量,需要用到标签,示例如下:
struct hhh{
int a;
char b;
}
这种方法并没有创建任何变量,而是把标签和成员列表绑定在一起,标签的作用就是标识了一种类型,以后使用相同标签声明的变量就是同一种类型的结构体变量。定义变量示例如下:
struct hhh ss,st;
此时ss和st就是同一种类型的变量了,就可以相互赋值,示例如下:
#include <stdio.h>
struct hhh{
int a;
char b;
};
struct hhh ss, st;
int main(void)
{
scanf("%d %c", &ss.a,&ss.b);
printf("ss的值分别为:%d %c\n", ss.a, ss.b);
st = ss;
printf("st的值分别为:%d %c\n", st.a, st.b);
return 0;
}
运行结果如下:
typedef
使用typedef是另外一种创建相同类型的结构体变量的方法,示例如下:
typedef struct{
int a;
char b;
}hhh;
该方法和标签方法的区别是hhh是一个类型名,而不是标签,因此定义变量的方法就不同了,定义变量示例如下:
hhh ss,st;
结构体的自引用
方法一
在使用C/C++编写链表程序时,会经常用到结构体的自引用,也就是一个结构体的成员包含该类型的结构体变量,一个错误用法如下:
struct hhh{
int data;
struct hhh next;
}
上述方法是错误的,因为next是一个结构体变量,但是"struct hhh"类型的长度不确定,结构体变量next内部也是相同结构,因此编译器会一直递归寻找该类型的长度,却没有终点。
struct hhh{
int data;
struct hhh *next;
}
这种方法是正确的,和上述程序的区别是next是指针变量,指针变量的长度是一个确定的值,在32位系统下,任何类型的指针变量都是4个字节,因此该结构体的长度是确定的,next存储的是一个该类型变量的地址。
方法二
也可使用typedef方法完成结构体的自引用,首先展示一个错误用法,示例如下:
typedef struct{
int data;
ss *next;
}ss;
这种方法是错误的,因为类型名ss在该结构体声明的末尾才定义,却在结构体内部使用了,此时ss还没定义,自然会报错了,正确用法的实例如下:
typedef struct hhh{
int data;
struct hhh *next;
}ss,*st;
这种方法将typedef和标签结合起来,结构体内部使用标签声明变量,该方法声明了ss类型的结构体和指向ss类型的指针st,形式简单,经常用于链表的编程