5.常量与变量

一、初步理解

无论变量还是常量,都是如今编程语言中很通用的概念,只不过在不同编程语言中的实现细节、使用方法会有些许差异。

首先来看看常量。

所谓常量,大致意思就是不可修改保持不变的量,它对应于编程中的一个基本底层需求:存放不希望被修改的数据

比如数学中的Πe等常数,有修改的必要吗?

一旦允许它被修改,那么在大型项目中,我们就无法保证别人不会修改它,这就很容易引发事故。

这里举的数学常数可能大家都知道,觉得不会有这种问题,可如果是天文常数、物理常数呢?那么多!你也不可能让每个人都知道它是个常数,不可更改吧?

为了杜绝这种情况,大部分语言本身都是支持常量的,并且基本使用的都是const关键字来声明一个常量。

并且由于常量本身不可修改的限制,一般都会要求你在声明变量的同时进行赋值,以C/C++为例:

const int a=10;//常量
const int b;// 错误,必须在声明的同时对其进行赋值,因为后续不允许对它进行修改了。

之后,一旦你试图去修改这个常量,那么你写的代码根本就通不过编译,这就从根本上杜绝了修改的可能性。

与之对应的就是变量,也就是可变的量,它对应于编程的一个基本底层需求:动态存储、修改数据

编程语言的根本目的,是让我们人类可以用一种尽可能简单、优雅、准确的方式去告诉计算机怎么处理数据。

如果你觉得编程语言一点都不简单,也并不是你的错,因为随着编程语言本身越来越简单、优雅、强大,它能实现的功能就会越多,社会对其的期望就会越大,对应的学习要求、难度等等也会随之上升,但实际上这并不是编程语言本身的问题,相比于以前的编程语言(机器码、汇编),现代编程语言都是越来越简单、优雅的(go、rust、kotlin)。

无论是软件、游戏,还是视频、音乐,其本质都是数据,更准确的来说,都是一堆01

虽然常量也可以存这些数据,但一般没人这么做:用十六进制编辑器打开这些文件,然后再将里面的数据直接复制到代码中,并赋值给常量,就能将数据编译进文件中。

那么这时候就需要变量了,它可以动态修改数据,这里还是以C/C++为例:

int a;
a=10;

能动态修改就意味着,你可以在程序运行过程中来接受、处理数据。

比如当你用音乐播放器打开一个音乐文件、视频播放器打开一个视频文件,这里的播放器就是已经编译生成的可执行文件了。

而这些文件数据就是在程序运行起来之后,才动态读取进行处理的,这就是变量的作用。

一般就实际开发而言,变量肯定比常量用的多。

二、命名规则

无论变量还是常量,说白了就是给一块内存取一个名字,既然是名字,那肯定就有一定的规范,不能让你乱取。

比如在编程语言中通常用=符号来赋值,如果你将这个符号作为变量名一部分,就肯定会问题,编译器无法识别。

目前就我所知,也许是编程传统所致,大部分正规的编程语言,所使用的变量命名规则字符集都是一样的:

  • 字母:a-z A-Z
  • 数字:0-9
  • 下划线:_

之所以有这个正规的限定,是因为有些离奇的编程语言,编程过程中甚至都不需要用字母,比如:Brainfuck

上面的字母、数字、下划线可以任意组合,就可以作为变量名:

int aAv90=10;
int _a8z_=20;

但唯独不可以将其数字放在最前面:

int 9abc_=10;

这种将数字放在最前面的就是错误的命名方式。

其原因在于,将数字放在名字前面,编译器无法识别这是一个数字还是名字,因为编程语言中是存在书写其它格式数字需求的,比如0x12,以数字0开头,并且既有数字也有字母,但这是一个十六进制的数字,而不是变量名。

其实不仅仅是变量名,程序中任何需要你自己取名的地方,基本都是这个规则。

而在一些现代语言中,比如rustgo,甚至会给一些特殊的名字赋予一些特殊的含义。

比如C++中暴露方法是在类中使用public关键字,比较麻烦。

而在Go中直接就默认规定了在模块中,函数名的首字母大写就是公开的,小写就是私有的。

rust语言中,如果一个变量声明了但不使用,编译器就会报警告,那么你就可以用下划线_作为变量名的开始,这样程序就不会报警告了。

三、作用域

取名字,听着简单,但其实有些时候并不简单,取名这个过程的本质,是给申请的一块内存取名字,方便我们后面使用。

然而一个类型的变量,比如时间,常见的名字也就那么几个,以至于很多时候就出现一种用无可用的地步,于是就开始添加数字、随便使用个字母等等。

比如:

int time1;
int t1;

而作用域这个概念,在一定程度上就可以解决这个问题。

比如C/C++中的作用域就是一个大括号表示的:

int time = 1;//外层定义一个time变量
{
    time = 3;//使用的外层time,从1改为3
    int time = 2; //内层再定义一个time变量,正确,不在同一个作用域
    time = 4;//使用的内层time,从2改为4
}

事实上大多数语言都继承了这个传统:用大括号限定一个变量的作用范围

但也有例外,比如python,就是用空格代替大括号来限定,

通过这种限定一个变量使用范围的方式,就可以让我们重复使用一个名字来命名变量了。

并且它有一套固有使用的规则:从使用变量的地方往前看,使用最近的那一个

如果该作用域没有这个变量名,那就会往外层找,如果一直找到最外层都没有,那就报错。

注意,它不会向内层寻找,比如下面这种代码就是错误的:

{
    int time = 2; //一旦脱离这个作用域,这个变量就不可用。
}
time = 5; //错误,只会向前找同作用域以及外层的变量

上面代码中的注释很重要:脱离作用域,变量就不可用

当然,你如果非要在C/C++中将它的地址取出来拿到外面用,兴许也能用,不过这种做法是绝对不推荐的,因为脱离作用域它就会被丢弃,那么这块内存上的数据就处于未知状态。

而处于最外层的,我们一般又将其称为全局变量,还是以C/C++为例:

int t=1; //全局变量
int main() {
}

也就是它不在任何一个大括号之内,就叫做全局。

此时它就在最外层,那么所有它后面的代码,如果使用t变量,就都会从当前层开始向前、向上找,如果都没有,那就会使用这个全局变量。

虽然这里都是用C/C++代码为例,但在大多数语言中都是通用的,只是实现方式不一样而已。

作者:余识
全部文章:0
会员文章:0
总阅读量:0
c/c++pythonrustJavaScriptwindowslinux