关键字
C 语言一共多少个关键字呢?一般的书上,都是 32 个 , 但是这个都是 C90(C89) 的标准。其实 C99 后又新增了5 个关键字。不过,目前主流的编译器,对 C99 支持的并不好,后面默认情况,使用 C90 ,即认为 32个关键字关键字-auto 如何使用:
一般在代码块中定义的变量,即局部变量,默认都是auto修饰的,不过一般省略,
#define _CRT_SECURE_NO_WARNINGS 1 #includeint main() { for (int i = 0; i < 10; i++) { printf("i=%dn", i); if (1) { auto int j = 0; //自动变量 printf("before: j=%dn", j); j += 1; printf("after : j=%dn", j); } } return 0; }
auto关键字已经很老,基本永不使用。
关键字-register
距离CPU越近的存储硬件,速度越快。
register会尽量将所修饰变量,放入CPU寄存区中,从而达到提高效率的目的
注意:register修饰的变量,不能取地址(因为已经放在寄存区中了,地址是内存相关的概念)
#define _CRT_SECURE_NO_WARNINGS 1 #includeint main() { register int a = 0; printf("&a = %pn", &a); return 0; }
一般不使用register了,因为现在的编译器,已经很智能了,能够进行比人更好的代码优化。早期编译器需要人为指定register,来进行手动优化,现在不需要了
关键字-extern
extern的正确使用
extern的错误使用
声明并没有开辟空间,所以不能进行赋值或者初始化
extern的建议
- extern int g_val;//变量声明必须带上extern!(防止,出现不知道是声明还是定义的问题)extern void show();//函数声明建议带上extern!
关键字-static
结论:
- static修饰全局变量,该变量只在本文件内被访问,不能被外部其他文件直接访问static修饰函数,该函数只在本文件内被访问,不能被外部其他文件直接访问static修饰局部变量,更改局部变量的生命周期,将其放在静态区
注意这个不是内存,而是操作系统中的进程地址空间
补充:全局变量和函数都可以跨文件使用,而跨文件使用又是为了做大型项目的时候方便交互
关键字-sizeof
#define _CRT_SECURE_NO_WARNINGS 1
#include
int main()
{
int a = 10;
printf("%d ", sizeof(a));
printf("%d ", sizeof a );
printf("%d ", sizeof(10));
printf("%d ", sizeof 10 );
printf("%d ", sizeof(int));
printf("%d ", sizeof int);
return 0;
}
运行后发现最后一个printf报错,sizeof int是错的注意sizeof这个关键字返回的是无符号的
编码好习惯:如果要定义全局变量,那么在前面加上g_
比如: 全局变量g_val
深入理解变量内容的存入和取出
signed int
b
= -
10
;
-10存入:
-10的原码:1000 0000 0000 0000 0000 0000 0000 1010-10的补码:1111 1111 1111 1111 1111 1111 1111 0101-10的补码:1111 1111 1111 1111 1111 1111 1111 0110
-10取出:
1000 0000 0000 0000 0000 0000 0000 1010
-10存入:unsigned int d = -10;
-10的原码:1000 0000 0000 0000 0000 0000 0000 1010-10的补码:1111 1111 1111 1111 1111 1111 1111 0101-10的补码:1111 1111 1111 1111 1111 1111 1111 0110
-10取出:
1111 1111 1111 1111 1111 1111 1111 0110
关键在于到底是%d打印,还是%u打印
总结:
- 存:字面数据必须先转成补码,再放入空间当中,所谓符号位,完全看数据本身是否携带+- 号。和变量是否有符号无关!
取:数据一定要先看变量本身类型,然后才决定要不要看最高符号位。如果不需要,直接二 进制转成十进制。如果需要,则需要转成原码,然后才能识别。(
当然,最高符号位在哪 里,又要明确大小端
)
编码好习惯:函数名的首字母大写,
比如:函数名My_strlen
如何理解char类型中的-128
-128的原码:1 1000 0000
-128的反码:1 0111 1111
-128的补码:1 1000 0000
char类型只有8个bit位,所以-128存入char中的时候会发生截断
-128在char中为1000 0000,他们规定这个1000 0000就当作-128注意1000 0000和0000 0000都可以表示0
数据类型的取值范围:-2^(n-1)到2^(n-1)-1
比如char取值范围:[-128,127]就是 [-2^7,2^7-1]比如short取值范围:[-2^15,2^15-1] 比如int取值范围:[-2^31,2^31-1]
关键字-bool(_bool)
c99之前,主要是c90是没有的,目前大部分书,都是认为没有的。因为书,一般都要落后于行业但是c99引入了_Bool类型(你没有看错,_Bool就是一个类型,不过在新增头文件stdbool.h中,被重新用宏写成了bool,为了保证C/C++兼容性)。
编码好习惯
在真假判断中,右边的代码比左边的代码更好,左边的代码会使人产生误解
关键字-double
double类型 变量与"零值"进行比较
#define _CRT_SECURE_NO_WARNINGS 1
#include
int main()
{
double x = 1.0;
double y = 0.1;
printf("%.50lfn", x);
printf("%.50lfn", y);
if ((x - 0.9) == y) {
printf("you can see me!n");
}
else {
printf("oops!n");
}
return 0;
}
#define _CRT_SECURE_NO_WARNINGS 1 #includeint main() { double x = 1.0; double y = 0.1; printf("%.50lfn", x); printf("%.50lfn", y); if ((x - 0.9) == y) { printf("you can see me!n"); } else { printf("oops!n"); } return 0; }
这个就叫做精度损失
解决方案:
#define _CRT_SECURE_NO_WARNINGS 1 #include#include #include int main() { double x = 1.0; double y = 0.1; printf("%.50lfn", x); printf("%.50lfn", y); if (fabs((x - 0.9) - y)< DBL_EPSILON) { printf("you can see me!n"); } else { printf("oops!n"); } return 0; }
这段代码中的fabs是一个求绝对值的函数fabs((x - 0.9) - y)< DBL_EPSILON这里不能写等于,
补充:()强制类型转换,不改变内存中的数据,只改变对应的类型
switch与case关键字
除非加上{ },不然switch和case不支持
编程好习惯:针对case:如果可以的话,把常见的指向情况放前面,把不常见的放后面
关键字-continue
在for循环中continue是跳到,改变循环变量那里
编程好习惯:使用循环语句的时候,尽量做到外小内大,一般来说这样的话,效率会高一点
关键字-void
在linux中void的大小是1,而在vs2019中void的大小是0void本身就被编译器解释为空类型,强制的不允许定义变量
补充:计算机中清空数据,只要设置该数据无效即可
为什么局部变量具有临时性
#define _CRT_SECURE_NO_WARNINGS 1
#include
#include
char* show()
{
char str[] = "hello bit";
return str;
}
int main()
{
char* s = show();
printf("%sn", s);
return 0;
}
具体的后面会说,但是值得注意的是printf也是一个函数,也会形成函数栈帧
关键字-return
#define _CRT_SECURE_NO_WARNINGS 1
#include
#include
char* show()
{
char str[] = "hello bit";
return str;
}
int main()
{
char* s = show();
printf("%sn", s);
return 0;
}
return返回的时候,会通过寄存器的方式,返回给函数调用方,及时没有接收也一样
变量的左右值
任何一个变量名,在不同的应用场景中,代表不同的含义!!!
关键字-const
#define _CRT_SECURE_NO_WARNINGS 1
#include
#include
int main()
{
const int i = 10;
int* p = (int*)&i;
printf("before:%dn", i);
*p = 20;
printf("after:%dn", i);
return 0;
}
const修饰变量的时候,虽然不能直接修改,但是可以间接到修改,const修饰变量,更重要的意义在于告诉程序员不要修改它,char *p ="hello bit!n"; 这个才是真正意义上的不可被修改
一个严谨的类型赋给一个不严谨的类型,报错 一个不严谨的类型赋给一个严谨的类型,不报错
补充:
#define _CRT_SECURE_NO_WARNINGS 1 #include#include int main() { int a = 10; int* p = &a; *p = 20; int b = *p; return 0; }
(类型相同)对指针进行解引用,就是指针指向的目标,*p就是a
关键字-volatile
这个关键字,就是不希望被编译器优化,不要CPU优化,达到稳定访问内存的目的
volatile const int a = 10;//正确
关键字-struct
空结构体的大小,在不同的编译器下是不同的
关键字-typedef
上面的unsigned int32 b;等价于char int a;所以报错
补充:
存储关键字有:auto,extern,register,static,typedef存储关键字,不可以同时出现,也就是说,在一个变量定义的时候,只能有一个



