今天已经学到c语言的最后一个难点了:结构体。
结构体的定义,形式如下:
struct 标识符(结构体名) 变量名
{
int id;
float score;
char name[10];
.......
} ; 可见在结构体定义时花括号内可以填入此结构体需要包含的全部内容,其中也可以是另外一个结构体。***最后右花括号结束后的 分号 一定不能少!
另一种定义形式:
struct
{
} s1 , s2;
此时由于没有结构体名,只能在定义结构体时一同定义好变量名,后续在程序中无法再定义该结构体下的新变量。
给结构体中的元素赋值:
struct ... name;
name . id = 110;name . score = 100;.......这样是给元素逐个赋值
还可以:struct student s = {1,100,"wang"};
个别初始化:
struct student s = {.score = 100};
或: struct student s = {. score = 100 , .name = "wang"}; 其余未赋值元素均为0
同时初始化多个元素时,每个元素之间用 逗号, 隔开。
结构体对齐:
不同的编译器有着不同的对齐数,例如Visual Studio Code的编译器的对齐数是8,Linux的编译器的对齐数是4
结构体总大小为最大对齐数的整数倍,结构体内每一个变量都会产生一个对齐数,取其最大的对齐数。
struct S1 { char c1; int i; char c2; };
其中:
c1 的对齐数是 1
i 的对齐数是 4
c2 的对齐数是 1
取三者变量中的最大对齐数是 4 ,也就是说结构体的最终大小是 4 个字节的整数倍。这里已经使用了 0 - 8个字节,也就是9个字节,所以需要继续向后开辟空间,直到结构体变量对应偏移量为 12 字节地址处的时候,为 4 的整数倍,所以最终这个代码开辟了 12 个字节的空间。
在表示结构体中的某元素是: (*s).id <=> s -> id
两者是等价的,后者更为精简好看。
结构体可以实现整体引用赋值:a1 = a2;其中a1 和 a2 是一个结构体的两个变量,这个操作把a2变量中的元素依次赋值给a1,结果是a1 和a2 保存的数值相同。
在编写头文件时,在这个头文件中不要包含另一个头文件,这样的操作会降低程序的运行效率,而是应该延迟包含。
输出缓冲区:输出缓冲区在遇到以下三种情况是才会将缓冲区的内容向外放出
1、遇到 \n 时
2、程序员手动调用 fflush()函数释放缓冲区
3、缓冲区满时,会将缓冲区中的所有数据一起放出。
单向链表:
单向链表是由一个个节点组成,节点没有名字,链表中的每个节点都包含一个存储空间,用于存储数据,以及一个指针,指向下一个节点的位置 达到逻辑上连续。这些节点在内存中是分散存储的,而不是连续存储的。这种分散存储的方式使得链表具有了动态内存分配的能力,可以在运行时根据需要创建和删除节点。