C语言中关于结构体的嵌套问题

1、结构体的定义

typedef struct tag {
 member-list
 } variable-list ;

创建一个别名为variable-list的结构体。其中struct是结构体关键字,tag是结构体的标志,member-list是结构体成员列表,variable-list是此结构体声明的变量。
一般情况下,tag、member-list、variable-list这三个部分至少要有2个。
注意只有结构体变量才会分配地址,结构体的定义是不分配地址的。结构体不能直接进行强制转换,只有结构体指针才能进行强制转换。

 struct Book
 { 
 	char title[20];//一个字符串表表示的title题目
	char author[20];//一个字符串表示的author作者
 	float value;//价格表示 
 };//这里只是声明 结构体的定义 
struct Book book1,book2;//结构体变量的定义 分配空间

book1.value;//引用结构体变量

2、结构体的存储
结构体的整体空间是占用空间最大的成员类型所占字节数的整数倍。编译器会自动补齐。

struct S1
{
   char a;
   int b;
   double c;
};

其中char a占用1字节,int b是4个字节,double c是8个字节。在定义char a和int b时,会先按4字节补齐,这两个定义就占用8个字节,在定义double c时,就不需要再进行补齐,因此整个结构体占用8+8=16个字节。
在这里插入图片描述
3、结构体变量初始化
在对结构体变量初始化时,要对结构体成员一 一赋值,不能跳过前面成员变量,而直接给后面成员赋初值,但是可以只赋值前面几个,对与后面未赋值的变量,如果是数值型,则会自动赋值为0,对于字符型,会自动赋初值为NULL,即‘\0’。
在这里插入图片描述
也可以在定义时直接赋值

struct Student
{ 
	char name[20];
	char sex;
	int number;
}stu1={"zhaozixuan",'M',12345};
//或者
struct Student
{ 
	char name[20];
	char sex;
	int number;
}struct Student stu1={"zhaozixuan",'M',12345};
//注意字符为‘ ’ 字符串为""

也可以在定义结构体之后逐个赋值

stu1.name="王伟";
stu1.sex='M';
stu1.number=12305;
//也可用strcpy函数进行赋值
strcpy(stu1.name,"王伟");

或者定义之后任意赋值

 struct Student stu1={
  .name="Wang",
  .number=12345,
  .sex='W', 
 };//可以对任意变量赋值

4、结构体指针
指针指向的是变量所占内存的首地址,在结构体中,指针指向的是结构体变量的起始地址,当然也可指向结构体变量的元素

  • 指向结构体变量的指针

    定义形式一般为
    struct 结构体名* 指针名;
    比如: struct Student* p;

    struct Student
    {	
    	char cName[20];
     	int number;
     	char csex;  
    }student1;
    struct Student*p;
    p=&student1;
    //若为结构体数组则
    struct Student stu1[5];
    struct Student*p;
    p=stu1;//因为stu1为结构体数组而p=stu1直接是指向stu1的首地址,就不用再加&符
    

    用结构体指针变量访问结构体变量成员有以下三种方式:

    p->cName
    (*p).cName 
    student1.cName
    

    p->number++; 是将结构体变量中number的值进行运算,然后再加一。

  • 指向结构体数组的指针
    想要用指针访问结构体数组的第n个数据时可以用

    struct Student stu1[5];
    struct Student*p;
    p=stu[n];
    (++p).number//是指向了结构体数组下一个元素的地址
    

5、结构体的嵌套
结构体可以有子引用和相互引用。
子引用:就是在结构体内部包含指向自身类型结构体的指针。
相互引用:就是在结构体中都包含指向其他结构体的指针。

  • 自引用结构体
struct tag_1{
    struct tag_1 *A; 
    int value;
};
tips:关于使用typedef
typedef struct tag_1{
struct tag_1 *A; 
int value;
}TAG;

没有使用typedef的话,在声明变量的时候必须是struct tag_1 t1;
若使用typedef的话定义的话,在声明变量时就可以TAG t1;相当于TAG==struct tag_1。
或者使用typedef,以下三种都可以。
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;

在自引用中定义的一个指向结构体的指针,看似是指向自身,其实是指向同一类型的不同结构。
链表和树的结构就都使用到此技巧。自身的结构体指针指向下一节点或者下一子树的地址。

有一种情况需要注意:

typedef struct {   //这里是结构体类型定义
 int a;
 s_ref *b;  //注意这句引用了结构体类型名
 char c;
}s_ref ;
这个结构体类型定义是为了定义类型名s_ref,但却失败了。因为结构体中就引用了结构类型名,而此时还没定义类型名。
可以改为如下:
typedef struct s_ref_t{   //这里是结构体类型定义和结构体标签
 int a;
 struct s_ref_t *b;  //注意这句与上面相同位置的区别,使用了标签
 char c;
}s_ref ;

  • 相互引用
//(使用“不完全声明”)
struct tag_a{
    struct tag_b *bp; 
    int value;
};
struct tag_b{
    struct tag_a *ap;
    int value;
};
typedef struct tag_a A;
typedef struct tag_b B;



struct tag_a; 
struct tag_b;
typedef struct tag_a A;
typedef struct tag_b B;
struct tag_a{
    struct tag_b *bp; 
    int value;
};
struct tag_b{
    struct tag_a *ap;
    int value;
};

  • 24
    点赞
  • 117
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值