ok,那下面我们就从赋值运算符开始。 那么说到赋值运算符,有的同学就开始觉得,
赋值运算符还有什么好讲的,不就是把一个值赋过去么?ok,你说的呀,
这是赋值运算符的基本功能。那么要用好赋值运算符,
那么除了了解它的基本功能之外,还需要再了解一些其他的要点。
我们就先来看一下它的基本功能,然后我们逐一看一下使用运算符
的要点。赋值运算符最基本的功能就是给赋值负号左边的这个变量
赋予一个值,这最基本的一个功能。除了最常用的这个功能之外,我们赋值运算符还出现在
变量定义里头。比方说,int a等于3,这其实相当于两句话。
第一句话,定义了一个变量a,第二句话,用赋值运算符给变量a赋值。
相当于两句话,那么需要说明的是呢,当然除了这种写法之外,我们也可以写成这样,int a
逗号,b,逗号,c,逗号,等于5,什么意思呢?我连续一下子定义3个变量,并且给变量c
赋值为5,这是这句话含义,所以说这个,就是说,大家千万不要写出来这种方式。
int a等于b等于c等于5,那么在定义,
变量定义的环节里头,变量之间是不能够连等的。
这种方式是错误的,这一定要小心。这是赋值运算符的基本功能。
那么,要用好赋值运算符,还需要知道一些什么呢?下面我们介绍一些使用赋值运算符的
要点。先看第一个,要点一,
当两边的类型不同的时候,会怎样呢?
也就是说啊,比方说有个赋值语句,a等于b,当
a和b的数据的类型不同的时候,
能赋值吗?如果赋值的话,会发生些什么呢?这是我们讨论的第一个要点。
我们先来看一个程序。首先在这个程序里头啊,我定义了好几个变量。比方说,int型的变量,
char型的变量,float型的变量,bool型的变量。
定义了好几个类型的变量,并且呢,它们互相赋值。 那这个时候会发生些什么呢?
我们先把结论告诉大家,然后我们再来验证一下,如果
等号两边的类型不一致的话,进行赋值,这个时候啊,就要发生
类型转换。那怎么转换呢?这么来转换。不管等号右边这个操作数是什么类型,
统统转换为等号左边的
类型。不管右边是什么,统统转换成左边的类型。
我们借着下边的例子,对着这个例子的实验结果,我们来分析一下。
先看第一步,我定义了一个int型的变量, int
i,并且呢给它赋值为,64.12345,
64.12345这是个小数,对吧,也就是个实型
的数。我们上次课曾经讲过,如果我们把一个小数直接写出来,
而不去说明它属于什么类型的数据的时候,系统将
把它默认为是什么类型啊?还记得吗?是double型。
这个是一个double型的数,也就是说它是一个双精度浮点数。
现在呢,要把一个双精度浮点数赋给一个整型的变量,可以吗?
可以。 一定会发生类型转换,怎么转呢?就是要把这个双精度的,
右边这个双精度的数据,转换成左边的整数。
那到底怎么去转呢?很好办。
既然它是一个小数,要转换成整数,那我就把小数部分整个一刀全部砍掉,
完事。然后把剩下的整数部分,赋到,赋到左边来。
也就是说,当右边是个小数的时候,要赋给一个整, 要赋给一个整数,我就把它拦腰砍断,把整数部分赋过去。
第一步里头,我们打印int i的时候,打出来64,这是对的。再看第二步,
现在int i里头是64,我要把它赋给一个char型的数。
既然64是一个位于0到255之间的数,所以可以直接去查一下测码表,
这个我们非常熟悉了,我们已经打印过很多遍了,是这个字符,@,
@这个字符。所以说char打印出来是这个字符。
再看第三部,第三部里头啊,我们把char型的这个i, 赋给了一个float型的数,char
i里头放的是64, 要把它赋给一个float型的数,float型的数是个小数,
那这个时候,无疑我们要补充小数位。
补充什么小数位呢,补0就行了,看第三个输出,就64.0000。
那么有的同学可能问了,嗳,这个地方为什么是64.0000,4个0啊?
这上次课我们讲过,因为cout打印的时候默认打印6位精度。再往下看,float型的i,我们要
把它赋给一个bool型的i,可以吗?
可以。怎么转换呢?float型的数要转换成
bool型的数。那以前我们讲过,bool型的数啊有这样一个 特点,它里面就放两个值,要么0,要么1。
0代表false,1代表true。 如果你赋给它一个非0的值,里面的值就是1;如果赋给它一个
0的值,里面的值就是0.那么在这,float i显然是一个非0的数,
所以说,赋过来以后,bool i里面放的是1.
所以最后打印出来是1.所以说,我们看到要点1,
完全成立。就是两边类型不同的时候,通通转变成左边的类型。
好,在我们再来看一下赋值运算的第二个要点。
也就说,当我们把一个长的数赋给一个短的数的时候,
会发生些什么呢?我们先来看一段程序。
在这个程序里头啊,我定义了两个变量。一个呢,
是字符型变量,char a,给它赋初值呢,是一个空格。
一个呢,是一个整型的变量, int
i,然后呢,给它赋初值,0x,16进制的,361.
有了这个赋值以后呢,大家可以想象一下在内存中的状况,我在这呢,画一张图。
上面的这个数,就对应着0x361,
底下的这个呢,就是1个字节,它对应着呢,这个字符数。
这个是这个,对应关系。那么,在这个程序中呢,
首先我们把int i以16进制的方式打印出来,确认一下。
然后呢,我们做了一个赋值,就是把这个 int
i啊,赋给了,char a。 int
i呢,是一个32位的数。 赋给了char a,char a呢,是一个8位的数。
一个32位的数给了一个8位的数,会发生什么呢?不知道。
但是呢,我们把结果打印一下。char a,我们先来看一下这个程序的运行结果。
实际上是这样的,361,然后a。 我们来分析一下这个结果,这个结果是这样的。
上面的这个数呢,跟361是匹配的,也就是说,它的第4位,是1.
再往上数4位,应该是6。这个对应着6,这个对应着1。
再往上数4位,对应着3。那么,前面呢,全都是0。
那么在赋值的过程中,其实做的事情是这样的。既然我打算要把一个32位的数,
赋给一个8位的数,
那我怎么做呢?我就把这个32位的数最后面的8位,
最低的8位,直接砍下来,然后呢,赋给这个8位的数。
这就是刚才所发生的事情。那么赋过来以后,
我们计算一下这个数。这个数的大小呢,刚好是
97。也就是说,它的运行结果,刚好是打印字符a。
这就是当把一个长数,赋给一个短数的时候,所发生的事情。
所做的事情呢,就是截取长数的第n位,直接送给这个短数。
这就是刚刚所发生的事情。
那么为了更清楚呢,我们来举一个例子。在这个例子里头呢,我们把一个
long型的数,赋给了一个short型的数,比方说,这两个数
之间的赋值。上面是一个long型的数据,
那么它占了呢,32个bit。下面呢,是一个short型的数据,它占了
16个bit。现在呢,我们要把一个long型的数据赋给这个16字节的short型的数据。
我们看一段相应的,相对应的程序。在这个程序里头啊,我们首先定义了
一个long型的变量,long
i,然后呢给它赋初值, 0x2AAAAAAA,这个16进制的数,对应着上面这个数,跟这个数是等价的。
利用我们前面学过的知识,大家可以推算一下,它的二进制表示就是这样的。接下来把它打印一下,
用10进制的这种方式。然后呢,我们把这样一个long
i, 赋给一个short 型的数short j,然后呢把这个short
j先按16进制打印。
一下,然后再按十进制打印一下。啊,这个结果呢是这样的。有的同学看到这个结果,哎呀,
会不会是错了呀?你看,首先呢,我们用十进制的方式打印了这个数,
也就是说,这句输出啊,程序的这句输出对应着这儿。
先把这个long int型的数打印出来。这是一个正数,好大的一个正数啊。
然后呢,我们把它赋给了一个短整型的数。
然后呢,再把这个短整型的数以十六进制打出来。哎,也没什么错。aaaa,最后把它以十进制的形式打出来。
怎么变成负的了呀,为什么变成负的了呀?很简单,
在赋值的过程中,当我们把一个长的数,例如上面这个长的数,
赋给底下这个短的数的时候,怎么办来着,把上面这个长的数
拦腰砍断,砍下相应的字节,直接把这个字节赋给
底下短的数。赋完了以后呢,我们再来观察这个短的数,它是一个
short型的数。这个时候程序发现它的第一位,系统发现它的第一位是一个1,
那足以证明它是一个什么类型的数啊? 是一个负数,啊它一点错都没有。
然后呢,把后面的这些求它的补码。然后算出来之后,它恰好等于
-21846,就等于这个数。透过这个例子,我们可以看出来很多问题。第一个问题,
当我们把一个长数赋给一个短数的时候,很好办,把这个长数后面相应的n位直接
拦腰砍下,砍下来以后直接赋给短数,这是第一个结论。第二个结论,
当我们把一个数赋给一个短数的时候,这个短数只管去接纳这个数,
等到程序对这个短数进行解释的时候,它发现这个短数的第一位是一个
1,它才不去管这个短数是怎么来的呢。按照整数的默存方式,
它被解释出来是多少就是多少。这是当我们把一个长数赋给一个短数的时候,
发生的情况。那有的同学可能问,那反过来呢?当把一个短数赋给
一个长数的时候呢?我们说啊,这是最好处理的一种情况。
也就是说原来是什么数,现在还是什么数。比方说,
我们定义了一个短整型的一个数,a=-1。现在呢我们把它赋给
一个int型的数b,啊,这就从十六位直接赋到32位了。
那这个结果会是什么呢?结果就是b=-1,也就是说原来a是什么数,
赋完了以后b还是什么数。那这个过程是怎么处理的呢?我们现在
举个例子来说明一下计算机的处理过程。比方说我们要把一个
short型的数赋给一个long型的数,这个时候怎么处理呢,计算机?
计算机这样来处理。如果short型的数为无符号数,那么,
那么先把short型的16位放到long型的低16位去,那么是long型的最高16位呢,
全部补0。啊是对无符号数。如果short型的数是一个有符号数,
那么,首先把short型的低16位放到long型的高16位。
然后去看符号位,如果short型的最高位,也就是说它的符号位是0,
那么long型的最高16位全部补0。
如果short型的最高位为1,则long型的高16位全部补1。
啊这就是它的处理情况。下面我们通过一个例子来印证一下。
这例子是这样的。啊,直接看这个例子。 在这个例子里头,我我定义了一个短整型的数,short
i=-123,然后呢我把它打印出来,确认一下。
然后,接下来呢,我把这个数赋给一个int型的数j。赋完了值以后呢,
先把这个 int j按照十六进制先打印一下,我看看,它到底发生了什么变化。
然后呢,再按十进制的这种方式把它打印出来,看它是不是没有,真的没有变。 那程序的运行结果呢就是这样的。首先,short
int型的 -123打印,按十六进制打印完是ff
85。然后呢,我们把这个short int型的数赋给一个int型的数j。
然后把这个j按照十六进制再打印一下,打印的结果是fff85。
看到这个结果是不是跟刚才我们讲过的是一样啊。因为short型的数的最高位是1,
全是f嘛,f全是1嘛。所以前面全都补1,
所以前面补的全都是f,没有错。然后呢,最后我们把这个,
最后呢,我们把这个int j,把它的十进制数打印出来,一看,-123,
的确没有变化。这就是当把一个短数赋给一个长数的时候,会发生些什么。
OK,这是要点之三。那么再看 要点之四。要点四呢是符号位的处理。
也就是说,当把一个有符号的数跟一个无符号的数进行互相赋值的时候,将会怎么办呢?
我们说啊这种情况也非常好处理。比方说,
这儿有一个有符号型的数,最高位是一个表示符号位。
那么这是一个无符号型的数,它的最高位呢表示数字位。那当它两个之间互相赋值的时候怎么办呢?很好办,
也是非常好处理的情况。直接搬运,直接赋值,我才不管最高位
是数字位还是符号位呢。比方说,当我们把一个有符号的数赋给一个无符号的数的时候,
系统怎么做呢?就把这个有符号的数原封不动地搬给这个无符号的数。
然后原来有符号数的最高位由符号位变成了一个数字位。
毫无疑问这个数会变得大。那么当把一个无符号的数赋给一个有符号数的时候呢,
相反,这个最高位就由原来的数字位变成了一个符号位。
下面我们通过一个例子来看一下。在这个程序里头我们看一下。
首先我们定义了一个无符号的数, unsigned int
i,给它赋出值呢,0xAAAAAA。其实这个数呢就完全等价于
我们下面画的这个数,无符号的数。先把它打印一下,按照十进制的方式把这个数打印出来,先看一下。
那么我们看一下结果,结果就是这样一个数,这是一个无符号的数。
然后呢,我们把这个数赋给了一个有符号的数,signed
int j, 把它赋给它。
赋给它以后呢,先用十六进制的方式把这个数打印出来。打印出来之后一看,全部都是A。
所以说赋值是没有问题的,是什么就是什么,直接搬过来。
然后呢,我们再把它按照十进制再打印一下。打印出来之后一看,是变成了一个负数,因为
这个数呢跟它是对应的,这就是一个负数,因为最高位呢是1。原来的最高位也是1,但是原来是一个数字位,
到这呢,变成了一个符号位。啊所以说这个数变成了一个负数。
这就是有符号数和无符号数之间的赋值处理。非常的简单,是什么就是什么。
那么我们对以上的几种情况啊做一个总结。第一个,
当赋值运算符两边的类型不同的时候,
要发生自动地类型转换。在类型转换的过程中,如果你把
一个长数赋给了一个短数,那计算机会怎么做呢。它会截取长数的
低位给这个短数。当把一个短数赋给一个长数的时候,
这是最好处理的情况,计算机会自动地保证原来是什么数,赋值完之后还是什么数。
第三种情况,符号位的处理,就是把一个有符号的数跟一个无符号的数进行互相赋值的时候,怎么处理呢,
直接赋值,我才不管最高位是数字位,还是符号位。
那么先赋完值,赋完值之后,重新按照新的数据类型进行
解析和判断。这是四种赋值的这个情况。
明确了这四种情况之后,我相信大家对赋值语句 应该会有一个大概的一个认识了。