第5章:常量与变量

前面我们已经学了数据类型,那么关于数据类型,我们拿它做什么的?

其实拿数据类型是来创建变量的 

       当我们要创建一个整型变量的时候用 int,当我们要创建一个字符变量的时候用 char,使用类型是用来创建变量的。我们现实生活中,你会发现:计算机语言是用来写代码来解决生活中的问题,必须有能力来描述生活中的一些现象,那么,生活中的一些数据它是有特点的:什么特点呢?

      1. 有些数据是不能变的:如血型(O 型血改成 B 型血就不行)、性别(有同学说性别可变吧,哈哈哈开个玩笑,性别我们暂时为不可变)、圆周率等等,有一些生活中的值是不能变的

      2. 有些数据一定可变:工资年龄体重等等,这样的东西都是可变的

      因此,我们可以明白:如果我们生活中真的有些数据不能变,有些数据可变的话,那这个时候我们用 C 语言去描述它的时候,C 语言这个时候就来了两个概念:一个是常量,一个是变量

下面我们来讲一讲关于常量和变量的知识点:

变量:用来描述能被改变的量

5.1 定义变量的方法

如何定义变量?给个类型,给个名字,等于一个数字

比如我想表示一个人的年龄,假定这个人的年龄是69,具体步骤如下:

       如上图所示:首先写出一个主函数,这就创建了一个变量,注意,前面 int 是类型,由类型来创建这个类型的变量,age 是变量的名字,如果你愿意的话,可以给它赋一个值,等号叫赋值,给它初始化一个值,后面的是数值

       当然,只有类型+变量的名字,不初始化,这样写可行吗?可行,但是不推荐。语法是允许的,但是不推荐(想必大家经常看罗翔老师讲课,法律普法的时候说:法律允许,但是不推荐、不提倡),因此我们这里也是一样,因此创建变量的时候,一定要给它一个初始化的值 -> 如果不给它初始化,局部变量会被赋成随机值,如果取地址访问内存,这属于野指针,这个是非常危险的

       再比如,我现在想来描述一下我的体重,我们可以定义一个体重的变量,那这个时候就是 float 类型或者 double 类型,都行,如果想精度高一点,给个 double;如果想精度低一点,给个 float,下图就是体重变量的创建:

       变量意味着可改, 比如 age 可以加加一下,就是说过了一年了,年龄增加一下,age 变成原 age + 1,增长了一岁;以及假设我要开始减体重了,一个月减10公斤,结果如下:

值得注意的是:a). 对于浮点型的打印,float 用 %f 打印,double 用 %lf 打印

                         b). 小数点后面默认带6位有效数字

                         c). 打印类型都有哪些?%d 是用来打印整型,%f 是用来打印 float,%lf 是用来打印 double

因此:变量是用来描述经常在变的量

5.2 变量的分类

变量分为哪两类呢?一类叫做局部变量,还有一类叫全局变量

什么是局部变量?在大括号内部定义的变量叫局部变量

什么是全局变量?在大括号外部定义的变量叫全部变量

        如第125行 a 在大括号内部定义,所以是局部变量,同理,在第120行 a 在大括号外部定义,所以是全局变量,如下如所示:

       那么,我要打印 a 的时候,那打印的是几呢?我定义了一个局部变量 a,我定义了一个局部变量也叫 a,打印的是几呢?答案是10,为什么是10呢?因为当局部变量和全局变量名字冲突的情况下,局部优先。当然,我们也不建议把局部变量和全局变量的名字写成一样的,如下如所示:

来一道经典题:变量是如何使用的呢?写一个代码,求两个整数的相加

注:解释一下以下代码的意思:

       第141行代码:程序的执行一定是从主函数开始进入,它后面一堆圆括号说明它是函数

       第142行代码:函数体头部

       第143行代码:定义一个整数 a,并初始化为0(局部变量不初始化是随机值,因此要初始化)

       第144行代码:定义一个整数 b,并初始化为0(局部变量不初始化是随机值,因此要初始化)

       第145行代码:与第147行代码前呼后应

       第146行代码,a 和 b 要录入两个值,scanf 叫输入,(printf 叫输出、打印),scanf 中前面指定的是格式,后面是我要把数据存放到哪里去(但是要给地址),具体就是:%d 就是说我们输入一个整型,再给个 %d 就是输入两个整型,如果中间有空格,意思就是输入的时候中间必须有空格,然后输入的数据放到放到 &a,&b<===>第一个%d 拿到的数字放到 a 里边去,第二个%d 拿到的数字放到 b 里边去

       第147行代码:我们为了能够存放两个整数,所以创建了一个 a,一个 b,因为我们要求和,求和是 a + b,a + b 的结果也得存起来,所以这个时候我们又得创建另一个变量(在145行),我们给它取名字叫 sum,就是说a + b 的结果能放到 sum里边去

       第150行代码:和第141行 int 类型形成一个前后呼应,即该函数执行完后得返回一个东西,int 表示的整型的意思(就是整数的意思),然后0也是整型,所以正好形成了前后呼应(return 0表示正常返回,return 1表示异常返回)

       第151行代码:函数体尾部

补充:

       在这里不建议大家使用 scanf_s 函数,因为这个函数是 VS 编译器提供的,不是 C 语言标准规定的,如果想要去用它,写了代码用了 scanf_s,那么这段代码只能在 VS 底下跑的通,其他平台上不能跑,是跑步过去的,所以我们在学习 C 语言的时候,用的时候,是不建议大家去学这个 scanf_s

      而如果非要用它,那请研究一下它如何使用,它的用法和 scanf 还是有一些区别的,如果没有研究就默用它,写出代码来,经常可能会写出一些 BUG 来,写出一些错误来。

      所以我们写出的代码在任何一个平台上都想跑的通,我们需要用 scanf,不用 scanf_s,因为 scanf_s 只有 VS 编译器才能认识它,当然,想用 scanf,把 #define _CRT_SECURE_NO_WARNINGS 一定要放在代码的第一行

 思考题:变量如何使用呢?

当想用空间存储数据的时候,就创造一个变量

思考题:第148行为什么不是 Printf("%\n",sum)?

因为我们要打印一个整数,%d 才叫打印整数,而不是%,来源于语法贵定,要写出%d 表示我要打印一个整数

5.3 变量的作用域

      什么是作用域?程序设计概念,通常来说,一段程序代码中所用到的名字并不总是有效/可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域,通俗来讲,就是:这个变量在哪里可以使用,哪里就是它的作用域

      如下如所示:在第8行创建的这个变量,在第9行可以使用,那这里就是它的作用域

       当我们在第10行,第9-11行这个大括号里边定义的变量 a,在第10行定义的 a,在第8行就不能使用了,因为 int a = 10中,a 的作用域就是 a 所在的这个大括号,现在出了这个大括号就不能用了,会出现未生命的标识符!如下图所示:

      同理,创建到后面依然不行,这个 a 只能在这个代码块内部使用,出了代码块就不行了,如下图所示:

      全局变量哪里都可以使用,从 main 函数的第一行开始往下,一直到 main 函数结束这个阶段都可以使用,如下如所示:

下图代码是错误的,不符合语法规定,如下图所示:

为什么出现了错误?因为代码都得写到函数里边去,变量的创建可以放到大括号的外边,但是执行性代码(打印一句话,变量赋值),必须放到一个大括号里边

      思考题:全局变量的作用域是整个工程?整个工程有点夸张了吧,是不是整个工程呢,接下来跟我走:我们再从 add.c 的源文件新建一个全局变量,并且赋值成2022,如下图所示:

大家注意,我们现在跨文件了,现在能不能在 test_4_2.c 的源文件中使用呢?如下图所示:

肯定是可以的,只不过直接用会出现未定义的标识符,那怎么用才可以呢?首先要声明一下变量,有一个关键字叫 extern,如下图所示:

       为什么要使用 extern?因为 test_4_2.c 源文件中变量类型是 int,我也写成int,test_4_2.c 源文件中变量名字叫 g_val,我也就写个 g_val,这就是声明,这个地方我们就对这个变量进行了一定的声明,我们只要这样声明了,下面使用起来就没有任何问题了

      其实本质上,int g_val 这个变量是存在的,我们只是在 add.c 这个源文件内部定义的,但是在test_4_2.c 源文件内部用,它不知道有这个东西,使用我们就声明一下

声明的意思就是:告诉你,我有这么一个东西

局部变量的作用域是就是变量所在的局部范围,全局变量的作用域是整个工程,整个工程任意一个地方都可以使用它(只要方法得当就可以)

5.4 变量的生命周期

什么是生命周期?就是变量的创建和销毁之间的时间段

生命周期是什么意思呢?

一个人的生命周期是什么是什么呢?就是他/她从出生,然后到死亡

那么一个变量的生命周期是什么呢?如下图所示:

       a 就是个局部变量,进入这个大括号里边的时候就是进入它的作用域了,它就可以使用了,而一旦要使用的时候,大家现象一下,这个变量是不是被创建出来才能被使用?使用这个局部变量 a 是进入它的局部范围去创建它,它的生命周期就开始了

      如果现在出了这个大括号内部就不能再使用 a 了,也就是说,出了这个大括号内部,我们不能使用它了,它就没有必要存在了,所以它的生命周期也在出大括号的一瞬间结束了,这个变量也就销毁了,因此:

局部变量的生命周期:进入局部范围生命开始,出局部范围生命结束

全局变量的生命周期:程序的生命周期

本章重要的知识点:

1. 作用域:这个变量在哪里可以使用,哪里就是它的作用域

2. 生命周期:变量的创建和销毁之间的时间段

3. 局部变量的作用域:就是变量所在的局部范围

4. 全局变量的作用域:整个工程

5. 局部变量的生命周期:进入局部范围生命开始,出局部范围生命结束

6. 全局变量的生命周期:程序的生命周期

补充:两个名字相同的全局变量,这种不可能出现,相同的全局变量名字是不能出现的,这种说法本身就是有问题的,因为全局变量名字出现了两个相同的,会导致重定义,变量名不能冲突,一旦冲突了,不能辨别哪个是真正的变量(类似于真假美猴王的问题)

常量:用来描述不能改变的量

什么叫常量呢?就是我们那些所谓不变的量就被称为常量

那么常量都有哪些常量呢?如图所示:

接下来,让我们一一列举:

      5.5 字面常量

      比如我现在写了一个3.14,这就是一个字面常量,就是我写出来之后,它就是个常数,它是不会变的,3.14能不能变成5呢?不能变,它已经固定死了,这就是个常量;

      再比如些写上个10,这也是个常量,这是整型常量;3.14是浮点型常量;再比如写个字符 a,也是一个常量,字符常量;再比如给个字符串 abcd,它也是个常量,它叫字符串常量。但是字面常量放在这好像也没有产生什么意义,但是它存在

     5.6 const修饰的常变量

      让 int num = 10,这个 num 本身是变量,为什么它是变量呢?因为 num 可变,使 num = 20再去打印,这个时候打印的结果就是20:

       确实,我们这个的地方打印出来了我们想要20了,说明这个地方 num 是可变的,那么 const 修饰的常变量是什么意思呢?就是说现在不想让这个 num 变,具体怎么弄呢?只要在 int num = 10的前面加上一个 const 就可以了,当我给它加上一个 const 的时候,num 这个时候自然而然这个地方就报错了,去编译代码的时候它就报错

       这个时候 const 修饰了 num 之后呢,num 就不能改了,左值指定 const 对象,就是左边这个对象是被 const 修饰的,被 const 修饰,就意味着我们这个值是不能被修改的,如下图1和2所示:

这就是 const 修饰的这个常变量,现在我们就把 num 叫常变量

       为什么说它是个常变量呢?因为它具有常属性(常属性就是不能被改变的属性)

       为什么说它又是个变量呢?因为它本来就是个变,它现在虽然不能变了,具有了常属性,但它本质上还是个变量

       我怎么证明它还是个变量呢?我们可以创建一个数组1,这个数组是10个元素,再创建另外一个数组2,依然给它初始化10个0,这样是不行的,因为:当我们在这创建这个数组的时候,指定这个大小的时候,我们用的 n 变量,也就是说:arr2[ ] 在创建的时候这个 n 必须是常量才可以,而现在 n 是个变量,就不行

       这个时候,有的同学就好奇了:这个地方 n 不行的时候(n 是变量不行),所以我给它加上const,const 加上之后这个地方的 n 不久变成常变量了吗,它具有常属性了啊,那么 const 它能不能放在这个地方呢?当我们去编译的时候,不行。如下图所示:

       为什么不行呢?因为我们这里需要的 n 是个常量!而 n 被 const 修饰之后它还是不能放在这,那说明它是不是常量?不是,所以它叫常变量,它的本质属性是个变量,只不过它被 const 修饰了一下,就是说根上还是个变量,它只是被 const 修饰了一下它不能被变了,所以叫常变量,但它本质上依旧是个变量,

      因此,需要常量的地方,这个 n 行不行呢?不行(就好比一个中国人在中国出生,后来去美国之后拿到了美国的绿卡,变成了美籍华人,它根上还是一个龙的传人,还是我们中国,只是他的国籍现在发生了一下变化而已,生动又形象的比喻了一下)

      因此第74行 int n 就是加上 const 修饰了一下,它具有了常属性,但它本质上还是个变量。->本质上是个变量,只不过具有了常属性而已

      补充:arr 是什么意思,arr 是数组,是个名字,就比如张三、李四、王五的意思,数组,就是一组数的意思,它里边可以放一组数字。

5.7 #define定义的标识符常量

       #define 可以去定义,#号是开头,后面是define(英语里边 define 就是定义的意思),这个时候我们定义了一个 MAX,它其实就是10000的意思,MAX 这个符号就是我们定义出来的,假设写一个临时变量 n,拿 MAX 给临时变量 n 赋值,如下图所示:

      由此可知:打印出来的结果就是10000,那说明确实这个 MAX 就是10000,10000赋给了 n,n 就是现在的10000,这个 MAX 就是 #define 定义的标识符常量

      为什么它是标识符常量呢?为什么它是常量呢?因为 MAX 不能改,假如现在 MAX 改成20000,改不了,这样是不行的,这样的改法是不行得到,MAX 是个标识符常量,它是不能改的,如图所示:

补充:#define 写在大括号里边,不会报错,在里边定义也是可以的

5.8. 枚举常量

      枚举常量是是什么?就是一般地用于那些可以一一列举的常量,在我们生活中,其实有一些量是可以被一一列举的,比如性别(男、女、中性、偏男两性、偏女两性、不完全男、不完全女),有7种;血型(也是固定的 ABO 血型);三原色(红绿蓝),星期(星期一到星期日)等等,所以生活中有很多的值,是可以一一列举出来的,那这些可以被一一列举的这种常量,我们把它叫做枚举常量

     举个例子,假设我们定义一个性别:

      枚举常量的性别方式怎么定义的呢?这里是个陌生的知识点,大家不用害怕,先接触一下,到第12章关键字我会讲解的,有一个关键字,叫 enum,这个叫枚举关键字,定义一个类型叫 Sex,然后后面有一个函数体(函数体最后要加分号),然后我们可以把性别它这种类型的变量的未来可能取值给它列出来,所以我们这里给上 MALE 这样一个值;还给上一个 FEMALE 这样一个值;SECRET 保密,那这写出的3个量就是枚举的未来可能取值,就是只能是这3种

      我现在用我这个类型,enum Sex 是一种枚举类型,我现在用它在第102行定义上 s 的一个变量,这个变量就表示一个人的性别,那这个时候这个变量的可能取值只要3种:一种是 MALE;要么就是 FEMALE;要么就是SECRET。反正只能给它赋值3个值里边其中一个,如图所示:

      补充:第88行这个枚举类型里边,放的 MALE、FEMALE、SECRET 这3个值就是枚举常量,其中,MALE、FEMALE、SECRET 3个值就是 enum Sex 这种类型的枚举变量它未来的可能取值,比如说第102行,我现在用这个类型创建了一个变量 s,那 s 的可能取值就是 MALE,另外,枚举和结构体非常相似

 思考题:为什么 MALE、FEMALE、SECRET 是常量?我们把 MALE、FEMALE、SECRET 可以打印出来看一下,如图所示:

因此:枚举常量,是常量,它的值默认是从0开始的,且这三个值也是不能改的,如图所示:

      需要注意的是,第92行这种情况不算改它的值,这是赋初值,给它赋上一个最开始的值,所以这个地方不是给它在改变它的值,是最开始我们就有个值,给它一个值。即使它是常量,常量最开始也得有个值(第92行是最开始给它一个值,当我们给了3之后,就不能再给它了),如图所示:

补充:

第88行 enum Sex 这是创建的一个枚举类型

第102行拿 enum Sex 这个枚举类型创建了一个变量叫 s

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值