【C语言进阶】自定义类型(1)结构体

结构体

目录

一、结构体类型的声明

结构的声明

特殊的声明

二、结构的自引用

结构体正确的自引用方式

三、结构体变量的定义和初始化

四、结构体内存对齐

结构体的对齐规则

为什么存在内存对齐?

修改默认对齐数

百度笔试题

五、结构体传参

六、结构体实现位段(位段的填充&可移植性)

什么是位段?

位段的内存分配

位段的跨平台问题

位段的应用


一、结构体类型的声明

首先我们来了解一下结构的基础知识:

结构是一些值的集合,这些值称为成员变量。结构的每个成员可以不同类型的变量。

如数组是一组相同类型的元素的集合,而结构体也是一些值的集合,结构体的每个成员可以是不同类型的。

结构的声明

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

//结构体关键字:struct
//结构体的标签:tag
//结构体的类型:struct tag
//结构的成员列表:member_list
//结构体变量列表:variable_list

例:

#include <stdio.h>
//声明一个结构体类型
//声明一个学生类型,是想通过学生类型来创建学生变量(对象)
//描述学生:属性 - 名字+性别+年龄+电话号码
struct Stu
{
    char name[20]; //名字
    char sex[10];  //性别
    int age;       //年龄
    char phone[12];//电话
}; //记住这里要加分号

struct Stu s3;//全局变量

int main()
{
    //创建的结构体变量
    struct Stu s1;
    struct Stu s2;
    return 0;
}

特殊的声明

在声明结构的时候,可以不完全的声明。

例:

//匿名结构体类型
struct
{
    int a;
    char c;
}sa;

struct
{
    int a;
    char c;
}* psa;//匿名结构体指针类型

 思考:在上面代码的基础上,下面的代码合法吗?

int main()
{
    psa = &sa;
    return 0;
}

执行结果:

 警告:编译器会把上面的两个声明当成完全不同的两个类型,所以是非法的。

结论:当两个匿名结构体类型内部的内容一样时,仍然是两个不同结构体类型 

二、结构的自引用

思考1:在结构中包含一个类型为该结构本身的成员是否可以呢?

//代码1
struct Node
{
    int data;
    struct Node next;
};

思考2:可行吗?如果可以,那sizeof(struct Node)是多少?

解答:不行。

假设代码1中的方式可以执行,那么在创建结构体的过程中,struct Node next由于结构体struct Node类型还没创建完成,所以其类型的大小是未知的,而struct Node类型的是否能成功创建又依赖于struct Node next类型大小的确定性。

所以这两者自相矛盾。因此上述方法不行!


结构体正确的自引用方式

//代码2
struct Node
{
    int data;//4 数据域
    struct Node* next;//4/8 指针域
};

思考3:这串代码为什么可以成功呢?

解答:首先此处结构体自应用方式并不是直接利用结构体来创建变量,而是创建指向该结构体类型的指针。

我们知道,指针的大小跟其所指向的类型无关,仅跟平台环境有关,32位平台指针大小为4个字节,64位平台,指针大小为8个字节。

正因为指针大小的确定性,所以再自引用的时候结构体类型的整体大小也是可以确定的。


思考4:这样写代码可行吗?

//代码3
typedef struct
{
    int data;
    Node *next;
}Node;

解答:不行

由于此时struct后面省略掉了Node,所以匿名重新命名结构体为Node,那么此时编译器就会不认识Node。(就好比先有鸡还是先有蛋)

因为结构体类型有重命名才能产生Node,而此时还未定义Node就在结构体内部使用了Node,所以会产生错误。

解决方案:

typedef struct Node
{
    int data;
    struct Node *next;
}Node;

评论 35
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HyDraZya

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值