4.4变量的作用域和生命周期
作用域(scope)是程序设计概念,通常来说,一段程序代码中所用到的名字并不总是有效和可用 的而限定这个名字的可用性的代码范围就是这个名字的作用域。
4.4.1:局部变量的作用域
局部变量的作用域是变量所在的局部范围。大家看下面这段代码:
#include <stdio.h> int main() { { int a = 5; } printf("%d", a); return 0; }
这里用了一对大括号把 int a = 5;这条语句括了起来,然后调用了printf函数,希望将a的值打印出来,能不能成功呢?
很明显,在编译的时候报错了,提示我们没有对a进行声明和定义。此时大家可能就会纳闷了,我不是已经定义了a=5嘛,为什么还会这样。其实,这就是变量作用域搞的鬼。在这里一个大括号就是一个代码块, a的作用域就被限制在了大括号里,只有在大括号里a的值才等于5,出了这个大括号a就不再等于5了。
4.4.2:全局变量的作用域
全局变量的作用域是整个工程。
此时在主函数中打印a的值,结果为5。
我们还可以通过extern来声明一个外部符号,如下图:
在同一个工程里我分别创建了“text.c”文件和“add.c”文件,在“add.c”里定义了一个变量a=5,如果我们想在“text.c”这个文件中用这个变量a,那只需要用extern将a声明一下即可,此时a也是全局变量。
4.4.3:变量的生命周期
变量的生命周期指的是变量的创建到变量的销毁之间的一个时间段。变量的生命周期和变量的作用域息息相关,在进入作用域时创建变量,向操作系统申请相应的字节来存储变量,出作用域时销毁,即就是把存储空间(前面申请来的字节)还给操作系统。
- 局部变量的生命周期是:进入作用域生命周期开始,出作用域生命周期结束。
- 全局变量的生命周期是:整个程序的生命周期。
4.5:常量
常量可分为以下四大类:
- 字面常量
- const修饰的常变量
- #define定义的标识符常量
- 枚举常量
下面逐一为大家介绍:
字面常量
int main() { 1; //数字常量 2; //数字常量 3.14; //数字常量 'a'; //字符常量 'c'; //字符常量 "abcde"; //字符串常量 return 0; }
这里需要注意的是字符常量要用一对单引号(' ')引起来,字符串常量要用一对双引号(" ")引起来。
const修饰的常变量
可以看到代码的第9行报错了,它提示我们表达式必须是可修改的左值,这就意味着此时的a是一个等于5的常量,后面不能对a重新修改赋值。但常变量,它的本质其实还是一个变量,证明如下:
箭头指向的是一条定义数组的语句,先大概介绍一下数组,数组就是向操作系统申请一块连续的存储空间用来存储多个相同类型的数据,如上图,[ ]里的数字代表的是数组长度,就是说这个数组可存多少个int型数据,后面的{0}是对数组进行初始化,大家先知道即可,后面会细讲。上图[ ]里面是a,我们本意是希望这个数组的长度为5,可以存储5个数据,但运行的时候程序却报错了提示我们[ ]里必须是一个常量值,这也就意味着这里的a其实是一个变量。由此可见,虽然我们定义了一个常变量a=5,但这个a本质上还是一个变量,这一点大家一定要注意!
#define定义的标识符常量
还是上面的证明方法,首先我们用#define定义一个标识符常量M,让它等于10,此时我们让[ ]里是M,希望得到一个长度为10的数组,此时的代码编译顺利通过了。 可见这里的M是一个货真价实的常量。
枚举常量
枚举的意思就是一一列举,比如我们可以将所有的血型一一列举出来,可以将三原色一一列举出来等等,这些都叫枚举。
上图的代码,定义了一个枚举类型,它的可能取值是RED,GREEN,BLUE,在主函数中把他们依次打印出来结果是0,1,2。枚举常量的取值是从0开始依次增加的整数。
上图代码的15行希望对RED重新赋值成100,但编译的时候却报错了提示我们表达式必须是可修改的左值,因此这里的枚举常量RED也是一个实实在在的常量,不可以对其重新赋值。
4.6:声明和定义
int a; int b=5;
其中第一条语句声明了一个整型变量(int型)a,第二条语句则是定义了一个整型变量b,它等于5。声明仅仅是告诉编译器我这里有一个整型变量,它的名字是a。定义则是比声明多了一个赋值,比如我们定义b=5,此时编译器给b分配了4个字节的存储空间。下面以具体的例子来看看声明和定义的区别。
上面这段代码在最后一行定义了a=5;希望在主函数中将a的值打印出来,但编译的时候出了问题,它提示我们‘a’是未声明的标识符。原因是当代码执行到22行的时候,它并不知道a是什么,在此之前并没有对a进行任何的声名或者定义。怎么解决呢?看下图代码:
可见只要在最开始添加一条声明语句,告诉编译器这里有一个整型变量a,最后就可以把a正常输出了。
五:字符串+转义字符+注释
5.1:字符串
"abcde"
这种由双引号引起来的一串字符称为字符串字面值简称字符串。 需要注意的是:字符串的结束标志是一个 \0 的转义字符。在计算字符串长度的时候 \0 是结束标志,不算作字符串内容。
上图代码中定义了两个不同的字符串,分别是ch1和ch2,对它俩用了不同的初始化方法(注:[ ]为空也就是没有规定数组的长度,其真实长度会根据后面{ }中的初始化自行决定),其中ch1是一个字符一个字符进行初始化 ,通过监视窗口可以看出来ch1数组中只有3个字符'a','b','c'。对ch2则是用字符串进行初始化,通过监视窗口可以看出来ch2数组中有4个字符'a','b','c','\0'。再看看对这两个数组进行打印会有什么结果:
为什么ch1打印出来会是这种情况呢?原因是'\0'是字符串结束的标志,ch1数组在初始化时是一个字符一个字符进行的,并且我们没有把'\0'也放进ch1数组中,这就导致在打印ch1的时候,编译器会从a开始一直往后打印,知道出现'\0'位置。那么就会有人问了,'\0'究竟什么时候出现呢,这我还真没法回答你。在同一台电脑上运行n次这段代码,可能会出现n种不同的结果。当我们在初始化ch1的时候加上'\0',打印出来的结果就正常了:
接下来我们再来求一下字符串长度,C语言提供了一个库函数strlen,可以计算字符串的长度,统计的是'\0'之前字符的个数。用这个函数得调用#include <string.h>这个头文件。
通过代码的执行结果我们可以看出来这两个字符数组的长度都是3。
5.2:转义字符
转义字符顾名思义就是转变意思。下表是一些常见的转义字符。
这里重点介绍一下'\ddd'和'\xdd',先上代码:
第30行的语句是希望用%c的格式打印出转义字符'\101',那为什么最后的执行结果是A呢?首先我们要知道'\ddd'这个转义字符,转义后代表什么意思,它转后的字符值是与该八进制数字对应的ASCII字符(由于计算机的工作基于二进制也就是以0或1来表示,但是字符不便于计算机工作,因此人们就想了一个办法,那就是让每一个字符都对应一个数字,这样就方便计算机工作,因此就诞生了ASCII)。回到正题,根据前面提到的,那这里的'\101'就意味着与101这个八进制数字对应的ASCII字符,因为每个字符对应的ASCII代码都是十进制,所以我们先要把八进制下的101转化成十进制数字,转化后的结果是65,查ASCII表可以得知65对应的字符是A,所以打印结果是A。需要注意,这里的八进制数字和十六进制数字都不能太大,因为ASCII代码有范围限制,超出这个范围程序就会出错。别看一个转义字符都是由两个甚至多个字符组合而成就比如'\n'由'\','n',2个字符共同组成,但实际上'\n'就只代表一个字符,其实我们可以从两个方面看出之一点,首先就是它们的名字,它们叫做转义字符,只有一个才能被叫做字符,多个那就叫字符串了,其次我们也可以通过代码中对其的引用看出来,我们在引用这些转义字符的时候都用的是单引号(' '),这些都从侧面反映了转义字符在算字符数量的时候只代表一个。但也会出现陷阱,那就是,如果'\ddd'中ddd表示的八进制数字对应的十进制和'\xdd'中dd表示的十六进制数字对应的十进制超过ASCII代码的范围。此时代码编译时就会出错,如下图:字符串"c:\test\622\test.c"中'\622'其中八进制数字622对应的十进制是402,此时的402已经远远超过了ASCII代码的范围了,没有任何一个字符的ASCIID代码是402。
还有一个陷阱那就是八进制数字中不能有超过大于等于8的,下面代码展示的字符串中\628,由于八进制数字中不可能存在比7大的数,所以这里的'\62'算一个转义字符,'8'算一个字符。这样数下来这个字符串的长度就是14。
5.3:注释
- 代码中有不需要的代码可以直接删除,也可以注释掉。
- 代码中有些代码比较难懂,可以加一下注释文字
具体方法主要有以下两种:
/*你最棒*/ //那最棒
/**/是将/*中间的内容注释掉,而//则是把//这一行//后面的所有内容注释掉。
六:选择语句
上图代码展示的就是一个最常见的if else 选择语句,它的意思是如果从键盘输入的值大于10则执打印出“好好学习”,如果输入的值小于3,则打印“天天向上”,如果大于等于3小于等于10则打印“万事顺意”。可见选择结构只会选择其中的一种情况去执行。可以有多个else if。
七:循环语句
- while语句
- for语句
- do...while语句
上面代码展示的是一个while循环,当a<10的时候就打印“万事顺利”,然后利用a++;这条语句对a+1,直到a=10为止不再打印。
结束语:
今天就先介绍到这里。萌新一枚,文章中可能有写的不对的地方,希望各位大佬能够指正,您的指正就是对我最大的帮助。