C语言实例梳理讲解常用关键字的用法
作者:嵌入式宇宙
一、C语言关键字详解
1. sizeof
sizeof相信大家并不陌生,其作用就是计算变量所占用的内存空间大小。sizeof的用法看着和函数很相似,但sizeof的真实身份确是:sizeof既是关键字,也是运算符,但不是函数! 这点需要大家牢记。还有非常重要的一点就是 sizeof中的表示式编译器不会进行编译处理,其原因就是sizeof是在编译的时候执行的,而C语言的运算符计算是在程序运行的时候执行的,故 sizeof里面的表达式是不会被执行的。下面以一个实际的程序来为大家演示一下。
源代码:
#include <stdio.h> int main() { int a = 3, b = 0; b = sizeof(a++); printf("a = %d, b = %d\n", a, b); return 0; }
运行结果:
a = 3, b = 4
看上面的程序就知道,虽然在sizeof表达式中变量 a 进行了自增1操作,但是 ++ 运算符是在程序执行的时候运行的,而sizeof表达式是在程序编译的时候运行的,所以 ++ 操作并不会被执行。
2. const
const关键字的作用就是将变量常量化。大家都知道变量是可以进行随意赋值的,但是常量不可以。而被const修饰的变量是不能够被赋值的,尽管如此,但是我们依旧有方法可以将其进行改变,看下面例子:
源代码:
#include <stdio.h> int main() { const int a = 3; //a = 4; //程序报错,因为变量a被const修饰成只读的变量了。 int *p = &a; *p = 8; printf("a = %d\n", a); return 0; }
运行结果:
a = 8
上面讲到const修饰的变量是不能够被赋值的,因此程序中注释的那一行会报错,这是合理的。在下面我们定义了一个指针指向变量 a ,并且通过指针的方式来改变变量 a 地址里面的内容,这样是合理的。我们可以这样来理解,首先定义一个变量 a , 那么这个变量 a 是具有可读可写属性的,用 const 对 a 进行修饰,可以理解成 const 去掉了变量 a 的写属性,只保留了读属性,所以不能再对 a 进行赋值了。接着我们定义了一个指针变量指向 a 的地址,这个新定义的指针变量没有被 const 修饰,所以具备可读可写属性,然后通过指针变量来对地址里面的值进行操作,相当于是间接改变了变量 a 里面的内容。所以const的作用可以简述成一句话,那就是 const修饰谁,谁不能被直接赋值,但是可以通过间接的方式来改变其内容。
3. static
static修饰的变量会存储在静态存储区,静态存储区默认值是0。
static的三个作用:
- static修饰的局部变量只会被初始化一次。
- static修饰的全局变量只能在本文件中被使用,不能在其他文件中使用。
- static修饰的全局函数只能在本文件中被使用,不能在其他文件中使用。
作用1将在下面的程序示例为大家演示,作用2和作用3将结合 extern 关键字为大家演示。
源代码:
#include <stdio.h> void func() { static int a = 2; int b = 2; a++; b++; printf("a = %d, b = %d\n", a, b); } int main() { int i = 0; for(i = 1; i <= 2; i++){ func(); } return 0; }
运行结果:
a = 3, b = 3
a = 4, b = 3
上面程序中,就是调用了两次 func() 函数,func() 函数的功能就是定义两个变量,并且执行加1操作,然后打印输出。变量 a 因为被 static 修饰,所以 a 被存储在静态存储区,静态存储区中的内容是要等程序结束完才会被释放。并且 a 只会在程序第一次进来的时候被初始化一次,后续再进来的时候不会再执行初始化操作,且保留函数上一次退出的时候的值。而变量 b 没有被 static 修饰,所以存储在栈区,栈区中的内容会在该函数结束的时候被回收,所以每次执行func() 函数变量 b 都会被重新赋值。
4. extern
extern一般只有在多文件编程的时候才会被用到,是用来修饰变量或函数的,并且告诉编译器,该变量或函数是在别的文件中被定义的,下面用一个实例来进行具体说明:
文件1源代码:
int a = 10; int add(int a, int b) { return a+b; }
文件2源代码:
#include <stdio.h> extern int a; extern int add(int a, int b); int main() { printf("a = %d, sum = %d\n", a, add(10, 20)); }
文件1和文件2同时运行结果:
a = 10, sum = 30
上面程序中在文件2中调用了文件1的变量和函数,因为变量和函数都是在文件1中定义的,所以我们想要引用到文件1中的变量或函数时就必须要用extern进行声明,否则就会报错。
假设我们在文件1中将变量和函数用static进行修饰,文件2不变。
改变后的文件1源代码
static int a = 10; static int add(int a, int b) { return a+b; }
这个时候再同时运行文件1和文件2就会报错。报错的原因就是在文件2中找不到变量和函数。其原因就是被static修饰的变量或函数只能在该文件中使用。
5. volatile
volatile的作用一句话概述的话就是防止编译器优化。 cpu读取变量的时候是先从内存中读取到寄存器,再从寄存器中读取变量的值,但是可能在一些情况下编译器认为某些变量的值没有发生变化,因此就省略了从内存中读取变量的操作,直接从寄存器中读取。但是这些值可能会被外部环境所改变,比如说是在中断或者别的线程里面改变,这个时候如果编译器没有及时更新变量在寄存器中的值就会导致读取错误。但如果将这个变量用volatile关键字修饰的话就可以保证cpu在读取变量的时候一定会从内存中读取到寄存器,这样就可以保证读取变量的值不出错。
6. typedef
typedef的作用就是为已有类型取别名,注意typedef只是取别名,而不是创造出一个新的类型。
源代码:
#include <stdio.h> int main() { typedef int u32; u32 a = 10, b = 20; //等价于 int a = 10, b = 20; printf("a+b = %d\n", a+b); return 0; }
运行结果:
a+b = 30
上面代码中使用 typedef 将 int 类型取名为 u32,对于编译器而言,只要是看到 u32 都会默认将其转换为 int 。取别名主要是方便我们来写和阅读代码,而并不会说是创造了新类型。
7. enum
enum就是枚举类型,因为我们有的变量可能取值范围就是那么几个值,不会出现别的值。像这种情况下我们就最好使用枚举类型,注意的是枚举的值默认是从0开始的,后面的值以此增加,如果我们对枚举变量中某个值进行手动赋值,那么被手动赋值的后面那个值会在此基础上加1。举个实例为大家具体讲解:
源代码:
#include <stdio.h> /*0, 1, 2, 3, 4, 5, 6*/ enum weekday{Monday, Tuesday, Wednesday, Thursday, Friday, Staurday, Sunday}; /*0, 1, 5, 6, 7*/ enum num{ONE, TWO, THREE=5, FOUR, FIVE}; int main() { enum weekday day = 3; day = Thursday; enum num number = FIVE; printf("day = %d, number = %d\n", day, number); return 0; }
运行结果:
day = 3, number = 7
8. continue
continue用法两大注意项:
(1)continue只能用在循环体当中。
(2)continue的作用是结束本次循环,进入到下一次循环。
源代码:
#include <stdio.h> int main() { int i; int a[5] = {12, 13, 5, 11, 10}; for(i = 0; i < 5; i++){ if(a[i] < 10){ continue; } printf("a[%d] = %d\n", i, a[i]); } return 0; }
运行结果:
a[0] = 12
a[1] = 13
a[3] = 11
a[4] = 10
从上面程序可以看出,a[2] 的结果是 5,所以结束本次循环进入下次循环,所以当 i 的值为 2 的时候不会输出打印。
9. break
break用法两大注意项:
(1)break只能用于循环体或 switch…case 语句中。
(2)break的作用是跳出本循环体外,值得注意的是如果有多层循环嵌套的话,break是只能跳出它所在的那一层循环体。
源代码:
#include <stdio.h> int main() { int i; int a[5] = {12, 13, 5, 11, 10}; for(i = 0; i < 5; i++){ if(a[i] < 10){ break; } printf("a[%d] = %d\n", i, a[i]); } return 0; }
运行结果:
a[0] = 12
a[1] = 13
从上面程序看,a[2] 的结果是 5,break就直接跳出了循环体,然后程序就结束运行了。因此从这里就能够看出continue关键字和break关键字最大的区别了,这两个关键字的区别也是常考的,大家可以好好熟悉。
到此这篇关于C语言实例梳理讲解常用关键字的用法的文章就介绍到这了,更多相关C语言关键字内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!