一、最易变的关键字 — volatile
#include <stdio.h> int pass = 1; int main() { while (pass) { //思考一下,这个代码有哪些地方,编译器是可以优化的。 } return 0; }
加volatile后:
#include <stdio.h> volatile int pass = 1;//加volatile int main() { while (pass) { } return 0; }
结论: volatile 忽略编译器的优化,保持内存可见性。
- const volatile int a = 10;const要求你不进行写入就可以,volatile要求每次都从内存中读取数据,两者并不冲突
- 虽然volatile就叫做易变关键字,但这里仅仅是描述它修饰的变量可能会变化,要编译器注意,并不是它要求对应变量必须 变化!这点要特别注意。
二、struct关键字
- 为什么要有结构体:计算的场景需要我们定义结构体
-
struct stu { char name[14]; int age; char sex; char addr[20]; };
定义一个结构体类型,本质是制作一个类型
-
结构体的本质是具有相同或不同的元素类型的集合
-
struct stu { char name[14]; int age; char sex; char addr[20]; }; int main() { struct stu x; x = { "ab", 19, 'w', "abc" }; return 0; }
该写法错误,结构体只能被整体初始化,不能被整体赋值,需要单个依次赋值
#include <stdio.h> struct stu { char name[14]; int age; char sex; char addr[20]; }; int main() { struct stu x; //x.name = "zhangsan";数组也只能整体被初始化,不能被整体赋值 strcpy(x.name, "zhnagsan"); x.age = 18; x.sex = 'w'; //x.addr = "abcd"; strcpy(x.addr, "abcd"); struct stu* p = &x; printf("%s\n", x.name); printf("%s\n", p->name);//两种写法均可 return 0; }
-
为什么结构体有两种访问方式:结构体在定义的地方,用点更合适,如果传参的话,用——>更合适
-
在函数传参时,极有可能传入一个结构体变量,任何函数传参都要形成临时拷贝,如果结构体特别大形成临时变量申请栈帧,效率太低,所以结构体传参建议使用指针(——>使用场景)
-
空结构体多大:不同编译器结果不同,vs2022会报错
柔性数组
- 一种在结构体中使用的特殊数组,在结构体中使用的特殊数组,在结构体末尾定义一个数组,其大小在运行时确定(需malloc分配)
-
#include <stdio.h> struct stu { char name[20]; int a[0];//int a[]也可以 }; int main() { printf("%d\n", sizeof(struct stu)); return 0; }
-
柔性数组只能作为结构体的最后一个成员,并且结构体的大小不包括柔性数组的大小,因此需要单独分配内存空间给柔性数组成员
-
因为柔性数组大小是在运行时确定的,如果柔性数组不是结构体的最后一个成员,那么后续成员的地址无法预测
三、union关键字
- 联合体所有成员起始地址在数值上一样
-
#include <stdio.h> union stu s { int a; char b;//b永远在a的低地址处 }; int main() { return 0; }
每一个都是联合体的第一个元素,每个元素都认为自己是联合体唯一的元素,任何一个变量开辟空间后一定会有地址,这个地址一定是他众多字节中最小的,任何变量,变量内部开辟空间都是从最低地址开始的
a,b,s在数组上相同
- 联合体的大小等于他所包含的最大成员的大小,联合体的所有成员共享同一块内存空间
- 结构体,联合体定义完后记得在{}加;
三、enum关键字
-
#include <stdio.h> enum color { red,//0 yelloe,//1 black,//2 }; int main() { //用枚举内部的常量初始化枚举变量 enum color c = red; //0 printf("%d\n", red); return 0; }
-
结构体联合体定义的都是变量,而枚举内部定义的都是常量(具有强相关性的常量),本质是整型,注意每个常量后面是逗号
四、typedef && #define
- typedef:类型重命名
-
typedef unsigned int u_int;//和宏不同,需要;结尾 typedef int* int_p; typedef struct stu { ...... }s;//将struct stu类型重命名为s //区别: struct stu { ...... }s//相当于定义一个全局变量s
- 推荐对结构体进行重命名
typedef和#define的区别
- int* a, b; a为int* ,b为int
- typedef int* int_p
- int_p a, b,a为int* , b为int*
- 不能把typedef看成类型替换,要理解成一个全新的类型
区别:①typedef不是类型替换,而是产生了一种全新的类型
②#define为文本替换
③typedf后面不能引入其他关键字来修饰该新类型
五、Sleep函数
- 功能:等待一段时间再继续执行
- 用法:Sleep(时间),头文件<windows.h>(Windows)<unisted.h>(Linux)
- Windows为毫秒,Linux下为秒(1秒 = 1000毫秒)
六、独立的if语句与if-else-if的区别
每个独立的if语句:
- 每个if语句都会独立判断条件,并执行相应的代码块
- 如果多个条件同时成立,那么多个代码块都会被执行
- 每个条件都会进行判断,无相互影响
if-else-if:
- 当某个条件满足时,执行相应代码块,不会再判断后面的其他条件
- 只有前面的条件不成立才会进行后面的判断
(关键字的学习要告一段落了,接下来学习的是符号啦!)
是冬至呀-CSDN博客https://blog.csdn.net/2302_81218652?spm=1010.2135.3001.5343