复习回顾:初学c语言8(操作符详解2)
补充:
一.结构体的特殊声明
1.匿名结构体类型

注意:
该类型只能使用一次,只能在定义结构体时定义变量
二.结构体的自引用

三.结构体内存对齐
偏移量 :数据结构某个成员相对于结构体的起始地址的字节距离
对齐数 :编译器的一个默认对齐数与该变量大小之中较小值
VS的默认对齐数为8,Linux中gcc没有默认对齐数,对齐数就是自身成员变量大小
结构体对齐规则:
1.结构体的第一个成员对齐到和结构体变量起始位置偏移量为0的地址处
2.第二个成员变量对齐到对齐数的整数倍(偏移量)的地址处
3.结构体总体大小为最大对齐数(每一个成员都有对齐数,最大对齐数为其中最大的)的整数倍
练习:
计算结构体的大小
代码1:
struct S1
{
char c1;
int i;
char c2;
};
printf("%d\n", sizeof(struct S1));
结果和解释:

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

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

四.为什么存在内存对齐呢?
原因:
1. 平台原因(移植原因):
不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定 类型的数据,否则抛出硬件异常。
2.性能原因:
对齐后,在要访问内存时只需访问一次,图例如下:

总体来说:用空间换取了时间
节省空间的方法:
1.要占用空间小的成员放一起
举例:

2.修改默认对齐数
指令 :#pragma pack(设置的默认对齐数)
关闭 :#pragma pack()
举例:

结构体的传参:
可以传结构体变量,也可以传结构体指针
注意:尽可能传结构体指针,传参的压栈而且是一份临时拷贝,压栈要花费时间,但拷贝结构体变量时可能拷贝十分大的数据,得开辟很大的空间存储,导致性能下降,而传结构体指针只要开辟4/8个字节空间存储地址,通过地址也可以找到结构体变量
五.结构体实现位段
1.什么是位段?
和结构体类似有俩个不同:
1.1成员必须是(大多数编译器下)int ,unsigned int,signed int(其他整形也行如char,但取决于编译器)
1.2定义成员后有个冒号和数字
举例:

2.位段的内存分配?
因为C语言标准尚未定义,不同平台可能有不同实现
分配时会遇到一下问题:

在vs中int被当作signed int 类型(最好写unsigned int 或signed int,俩者范围不一样,可能报错)
成员的分配从右向左
当⼀个结构包含两个位段,第⼆个位段成员⽐较⼤,⽆法容纳于第⼀个位段剩余的位时,会舍弃
举例:

图像:

注意 :一个字节内部bit位没有地址