今天关于结构体一些疑问, 在这里标记一下
1. 定义与声明
结构体的定义如下所示, struct 为结构体关键字, tag 为结构体的标志, member-list 为结构体成员列表, 其必须列出其所有成员; variable-list 为此结构体声明的变量.
- struct tag
- {member-list} variable-list ;
在一般情况下, tag,member-list,variable-list 这 3 部分至少要出现 2 个. 以下为示例:
- // 此声明声明了拥有 3 个成员的结构体, 分别为整型的 a, 字符型的 b 和双精度的 c
- // 同时又声明了结构体变量 s1
- // 这个结构体并没有标明其标签
- struct {
- int a;
- char b;
- double c;
- } s1;
- // 此声明声明了拥有 3 个成员的结构体, 分别为整型的 a, 字符型的 b 和双精度的 c
- // 结构体的标签被命名为 SIMPLE, 没有声明变量
- struct SIMPLE{
- int a;
- char b;
- double c;
- };
- // 用 SIMPLE 标签的结构体, 另外声明了变量 t1,t2,t3
struct SIMPLE t1, t2[20], *t3;
- // 也可以用 typedef 创建新类型
- typedef struct{
- int a;
- char b;
- double c;
- } Simple2;
- // 现在可以用 Simple2 作为类型声明新的结构体变量
- Simple2 u1, u2[20], *u3;
在上面的声明中, 第一个和第二声明被编译器当作两个完全不同的类型, 即使他们的成员列表是一样的, 如果令 t3=&s1, 则是非法的. 结构体的成员可以包含其他结构体, 也可以包含指向自己结构体类型的指针, 而通常这种指针的应用是为了实现一些更高级的数据结构如链表和树等.
如果两个结构体互相包含, 则需要对其中一个结构体进行不完整声明, 如下所示:
- // 结构体 A 中包含指向结构体 B 的指针
- struct A
- {
- struct B *partner;
- //other members;
- };
- // 结构体 B 中包含指向结构体 A 的指针, 在 A 声明完后, B 也随之进行声明
- struct B
- {
- struct A *partner;
- //other members;
- };
2. 自引用 结构体
1.1 不使用 typedef 时
错误的方式:
- struct tag_1
- {
- struct tag_1 A; /* 结构体 */
- int value;
- };
这种声明是错误的, 因为这种声明实际上是一个无限循环, 成员 b 是一个结构体, b 的内部还会有成员是结构体, 依次下去, 无线循环. 在分配内存的时候, 由于无限嵌套, 也无法确定这个结构体的长度, 所以这种方式是非法的.
正确的方式: (使用指针):
- struct tag_1
- {
- struct tag_1 *A; /* 指针 */
- int value;
- };
由于指针的长度是确定的 (在 32 位机器上指针长度为 4), 所以编译器能够确定该结构体的长度.
1.2 使用 typedef 时
错误的方式:
- typedef struct
- {
- int value;
- NODE *link; /* 虽然也使用指针, 但这里的问题是: NODE 尚未被定义 */
- } NODE;
这里的目的是使用 typedef 为结构体创建一个别名 NODEP. 但是这里是错误的, 因为类型名的作用域是从语句的结尾开始, 而在结构体内部是不能使用的, 因为还没定义.
正确的方式: 有三种, 差别不大, 使用哪种都可以.
- /* 方法一 */
- typedef struct tag_1{
- int value;
- struct tag_1 *link;
- } NODE;
- /* 方法二 */
- struct tag_2;
- typedef struct tag_2 NODE;
- struct tag_2{
- int value;
- NODE *link;
- };
- /* 方法三 */
- struct tag_3{
- int value;
- struct tag_3 *link;
- };
- typedef struct tag_3 NODE;
3. 相互引用 结构体
错误的方式:
- typedef struct tag_a{
- int value;
- B *bp; /* 类型 B 还没有被定义 */
- } A;
- typedef struct tag_b{
- int value;
- A *ap;
- } B;
错误的原因和上面一样, 这里类型 B 在定义之 前 就被使用.
正确的方式:(使用 "不完全声明")
- /* 方法一 */
- struct tag_a{
- struct tag_b *bp; /* 这里 struct tag_b 还没有定义, 但编译器可以接受 */
- int value;
- };
- struct tag_b{
- struct tag_a *ap;
- int value;
- };
- typedef struct tag_a A;
- typedef struct tag_b B;
- /* 方法二 */
- struct tag_a; /* 使用结构体的不完整声明 (incomplete declaration) */
- struct tag_b;
- typedef struct tag_a A;
- typedef struct tag_b B;
- struct tag_a{
- struct tag_b *bp; /* 这里 struct tag_b 还没有定义, 但编译器可以接受 */
- int value;
- };
- struct tag_b{
- struct tag_a *ap;
- int value;
- };
来源: http://www.bubuko.com/infodetail-2645626.html