左值、右值——从int a = 3;谈起

今天,我们来讲c语言最常见,最微不足道的一行代码:int a = 3

千万别小看了这一行代码,它几乎囊括了c语言里的全部内容。

1.       int a = 3;声明了一个变量,而且是一个int型的变量。

2.       int a = 3;在声明变量的同时,给a这个变量赋了一个初值。

要彻底搞清楚这行代码,就应该搞清楚这样几个问题:

1.       什么是声明?

2.       什么是变量?

3.       什么是赋值?

好,我们就来一个一个的讨论:

1.什么是声明呢,举一个例子吧!“排排坐,分果果”是大家再熟悉不过的了。在这里:我们设想有一群小孩坐成一排,有一个老师给他们分水果。我们告诉老师说有一个苹果,老师就会把这个苹果分给某个小孩。

在这个例子中,“老师”就相当于编译器(compiler),“小孩”就相当于一块一块的内存空间,“我们告诉老师说有一个苹果”就相当于“声明”。因此,所谓声明(这里只考虑变量声明),就是通知编译器一件事。

具体通知编译器什么呢?这就要看我们是声明什么?比如,我们声明一个变量,我们就跟编译器说:我要一个变量,而且是一个整形变量。这就好比我们告诉老师说:我有一个水果,而且是一个苹果。水果就是一个变量,而苹果就是变量类型。

好,为什么要声明呢?大家都知道,计算机只看得懂地址,而要我们去记住每一个地址,那是相当不现实的,就好比我把int a = 3;写成int 0x000000H = 3一样,一个变量还好说,变量一多恐怕就没人知道那些0x000000H, 0xfecadfH……是什么意思了,所以为了我们程序员的方便,我们给地址启一个名字,这样我们就能很快的记住它们了。这样是方便了我们,可是问题出来了,我们都知道a是一个整形的变量,可是电脑它不知道啊,怎么办呢?就通过编译器,通过编译器对我们的语言翻译,译成电脑看得懂的语言。所以,编译器就是一个“翻译员”,把我们说的“人语”翻译成电脑的“机器语”。这样一来,我们的工作就简化了,我们声明一个a,编译器就会为我们找一个内存来放这个a。至于放在哪里,我们就不知道了,也不必知道,我们只要能用a就可以了。回到我们上面的例子,我们只要告诉老师说我要分一个苹果,至于老师把苹果分给哪个小朋友我们就不知道了。

下面,我们接着说变量。可以毫不夸张的说没有变量就没有程序。变量的重要性可见一斑。

那到底什么是变量呢?

变量的定义:变量是一个数学抽象,一种数学模型。没有很好的定义,就给出一个描述吧:变量有一个名字,有一个存放的位置,有一个存放的值,存放的值有一个类型。所以,名字叫变量名,存放的位置叫地址,存放的值叫变量的值,值的类型叫变量类型。就像一个编号的盒子里放在一个鸡蛋。这个整体就是一个变量。在计算机里就是一块存着数据的内存。

变量名与地址:计算机它为了自己的方便给每个内存块启好了名字,这套启名方案只有它自己知道。电脑启的名字叫地址。而我们也有自己的启名方案,我们启的名字叫变量名。这两套方案被编译器统一起来。所以变量名与地址0x00000H都是一个意思,或者说存在一一对应的关系。只是属于我们(人)的方案, 0x000000H 属于电脑的方案。两者的实质是一样的。

变量的值:我觉得说值不是很好,说数据(data)更好一些。变量的值就是内存块里存放的数据。也就是那个放在盒子里的鸡蛋。

说完了变量,我们就来详细的说一下赋值,这个问题同样也是语言的很有魅力的一个地方。再把int a = 3; 这个代码拿出来说。这一行代码其实是两行:int a; a = 3; int a;就是声明,这里就不再讨论了。a = 3; 就是赋值。在讲赋值之前,我们先引入两个非常重要的概念:左值,右值。

顾名思义,左值就是放在“=”左边的值;右值就是放在“=”右边的值。(“=”读作赋值号,不是等号)这不是废话吗?这还要说!先别急,等等你就能体会到这两句丰富的意义了。

左值的更确切定义:标识存放数据的一个空间。是一个标志。

右值的更确切定义:一个数据。

请务必记住这个检证定理:左值只能是一个地址,它表示一个可以存数据的地方。右值只能是一个具体的数据。

再来看这个例子: a = 3;很显然,在“=”的左边,是左值;在“=”的右边,是右值。这个式子合法吗?

我们来证明一下,左值 a 是一个可以存数据的地方吗?在计算机里不就是0x00000H吗?是的,是一个地址的别名,是一个可以存数据的地方。

右值 3 是一个具体的数据吗?毫无疑问是的。因此 3 是一个合法的右值。

左值,右值都合法,所以 a = 3合法。证毕。

反过来看这个例子: 3 = a

证明:

1在“=”的左边,所以 3 是左值,但是它并不是一个可以存放数据的地方。所以它不是一个合法的左值。

2在“=”的右边,所以 a 是右值,它能表示一个具体的数据吗?可以,因为在这个变量里存放有数据。这个数据就是一个具体的值。所以,它是一个合法的右值。

3)由于 左值不合法,所以 3  a 不合法。证毕。

总结:变量既可以作左值,又可以作右值,作左值的时候,标识一个地址;作右值的时候,作一个具体的数据。好,现在我们就知道什么叫赋值了:赋值就是把一个具体的数据(右值)放到一个可以存数据的地方(用左值标识出来)。

再来看一个麻烦一点的例子: int a, b = 2 a = b + 3….(2)请问什么是左值?什么是右值?

是左值,是右值。这么简单。那就错了。请好好想想左、右值的定义。右值:放在“=”右边的值。是这样的(a = (b +3) 右值应该是 b+3的值。怎么这么奇怪。b+3是什么东西呢?b + 3叫做表达式。再讲这个例子之前,我们先来说一下表达式。

什么是表达式?和变量一样,表达式也只有描述性定义:表达式由三部分组成:有一个操作符,有一组操作数,有一个结果。结果是一个很重要的东西,但是经常被我们忽略。

就说b + 3(注意,后果没有;)就是一个表达式。“+”是操作符,“b”和 3”是操作数。它的结果是什么呢?变量里放着的值是 2 , 所以结果就是 2+3 = 5

这样我们就来证明 a = b + 3是否合法。

证明:

1是一个合法的左值,变量可以作左值。

2b+3 的值是5 ,是一个具体的数据,可以作右值。

因此, a = b + 3 是合法的。

反过来呢 b+3 = a是否合法?不合法(证明从略)

由此可以得出一个不完整的结论:一般情况下,表达式不能作左值。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值