C结构体 —— 小白详解

结构体是一种自定义的数据类型,程序员自己定义的结构体,可以有很大的操作空间,在c++中重要的特点之一就是类,类也帮助程序实现了对于对象的操作

既然结构体是一种数据类型,就可以通过类比
int a =0
来理解,int是整型数据类型,a是变量名,0是赋值给a变量的值,我们也称为初始化,结构体也有许多类似的性质,先看一个例子
struct S
{
int i;
char c;
};
语法:struct name//定义类型名
{
type_name;
type_name;
……
}name; //定义全局变量
这里是一个简单的结构体变量,变量名称就是类型就是struct S,这个struct表明是一个结构体类型,S是自定义的,也就是说程序员可以自定义类型名,这样做有什么好处呢,可以包含一个人的各种信息,这也是结构体的一个实用的特点,与我们生活中类比就是,我们每个人都有着各种信息,不能显示在我们表面,那这些信息就有一些专门收集起来的地方,比如文件夹,身份证,学生证等等,结构体就是这样的类型,举个例子,结构体表示学生证
struct Stu
{char name[20];
int id-number[10];
};
这就是一张c中的“学生证”,还可以将Stu改成其他的就是其他的信息收集处。这就是结构体的声明,结构体在使用之前是需要声明的,就像函数一样,但是不需要定义,声明的时候也不需要赋值初始值,只需要声明类型就好。这里在结构体最后有个分号是与众不同的地方,之所以要这个分号,是便于创建全局变量,int类型创建在函数外就好,但是结构体还需要声明,所以这里留了一个位置,当然,也可以不创建,建议别创建,不稳定。
声明之后,如何使用呢?
变量的初始化,就和int类型一样初始化就好,类型+名称+初始值
struct Stu s1 ={0};//变量名称s1,内部成员全部赋初始值0
或者
struct Stu s;
这是最简单的初始化方式
这里变量初始化注意的点是结构体需要打大括号
当然,也可以给特定值赋值,在这里赋值就像函数一样,对应位置放置对应的值
比如,
struct Stu s1 = {"zhangsan",1120242022}
也可以不用对应关系,但是要用到成员访问操作符,之后和指针一起讲
这里的变量声明中如果有数组,就要注意数组中的大括号或者字符串引用操作符
struct Stu
{
double weight[5];
int age;
};
struct Stu = {{60.0 60.0 60.0},20};
这样就是一个含有数组的结构体初始化
说到数组,int类型函数类型都有数组,结构体类型有没有呢?有的
struct Stu ss[2] = {{"lisi",1120241001},{"wangwu",1120241002}};
这就是结构体数组,访问形式也和普通数组访问一样,利用下标访问操作符

结构体成员访问操作符
结构体里的变量能不能灵活拿出来使用呢,可以,成员访问操作符.,还有一个指针访问结构体操作符->,对,结构体也有指针,而且有自己的特定访问操作符,不要以为结构体是什么高大上的东西,就是一个类型而已

那么具体的使用举例
printf("%s",s1.name);
输出结果就是zhangsan
指针举例
struct Stu* ps1 = &s1;
printf("%s",ps1 ->name);

这就是结构体成员访问的两种形式

那么,int类型的大小是4个字节,那结构体在内存中的大小是多少呢
这里的规则也很特殊,取决于结构体的“特殊“的类型,可以放很多数据类型,具体的规则是内存对齐

1、第一个变量从0偏移量开始装填自身大小内存
2、其他变量变量从对齐数的整数倍的偏移量开始开始装填内存空间
3、结构体的大小为最大对齐数的整数倍
(每个编译器都有默认的对齐数,vs2022的是8,单个变量的对齐数就是自身大小与默认对齐数相比小的那个)
4、嵌套结构体的对齐数为自身对齐数中最大的那个

struct S1
{
 char c1;
 int i;
 char c2;
};
printf("%d\n", sizeof(struct S1));

struct S2
{
 char c1;
 char c2;
 int i;
};
printf("%d\n", sizeof(struct S2));

struct S3
{
 double d;
 char c;
 int i;
};
printf("%d\n", sizeof(struct S3));

struct S4
{
 char c1;
 struct S3 s3;
 double d;
};
printf("%d\n", sizeof(struct S4))

这里有四个题目,一个个看便于理解,

第一个的结果是12,分析如图



第二个的结果是8,分析如图


第三个的结果是16,分析如图


第四个的结果是32,分析如图


为什么会有内存对齐规则,为了更好的可移植性,不同的编译器需要读取数据的形式不同,就是用空间换取读取时间的做法

这里的默认对齐数也可以自定义,利用
#pragma pack(1)//默认对齐数设置为1
#pragma pack()//恢复默认设置

小tips:结构体在函数中传递的时候建议传址
,而不建议传值,函数在传参的时候需要压栈,结构体过大,传参时创建新的空间导致性能下降

结构体实现位段
位段是一种自定义类型,相较于结构体,可以自定义数据大小,定义的是bit位,通过
具体形式:

当然也可以设置数值,如果超过空间大小会存在截断

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值