[音乐] 下面是一个C语言程序的例子,
那么这个例子当中有个x赋值为-1,然后呢,对于一个u,我们赋值为这样的一个数,
因为如果这一个变量是 一个int型的话,那么这一个值实际上是无法表示的,
但是如果是unsigned的话,那么这一个值是可以表示的,然后我们要打印这个
x,先按照无符号数来打印,然后再按照带符号数来打印,
u也是按无符号数和带符号数来打印,那打印的结果我们讲是32位机器上运行,
这个int型和unsigned int型都是32位的,这么的一个
那么字长是32位的,那么打印出来的结果应该是这样的,x是等于
这个值,然后等于-1,就是按照无符号数打印出来的结果是一个最,是一个很大的数,
按照带符号数打印,它是-1,u按照这个
无符号数打印,它还是赋的值,还是打印出来的,是这个,
如果把它转换成带符号数的话,它就是一个最小负数,32位的最小负数,
那么这个里面因为-1的补码,我们前面也讲过,也举过例子, 它的补码的表示是全1,
那么全1作为无符号数解释的时候,它就是等于2的32次方减1,
也就是2,1后面有32个
0,然后再减1,实际上最终得到32个1, 那么这一个实际上就是这样的一个数字,
2的31次方的无符号数表示,就是1后面有31个0,
31个0,这个形式大家前面已经看到过了,它实际上 解释成带符号数,也就是用补码来解释的时候,
它实际上是一个最小负数,最小负数,这个最小负数是等于负的2的32减1次方,也就是
负的2的31次方,那也就是等于这样的一个值,因此我们可以解释
为什么u最后打印出来的这个结果按照
带符号数来打印,它打印出来的是这样一个值,负的最小的负数,
那么,这个x原来是等于-1按照 无符号数打印的时候,它就是一个很大的值,
编译器在处理C语言程序的时候,
编译的时候,它的这个对于常数,对于一个常数
它的解释成的这个,给它规定的这个数据
类型,有一个约定,那么C90里面的约定是这样的,
当你给出的这个常数,它的范围在0到这个期间,
它就把它解释成int型的,如果是在这个期间的一个常数,就解释为unsigned int型的,
如果是在这个期间的一个常数就解释成 long long 型的,然后 就是unsigned
long long 型的,然后到了C99里面以后,它就这个 规则就变了,在这个0到2的
31次方减1,在这个范围内,跟C90还是一样,
还是一样,是int型的,然后只不过它把这个原来 的这两个范围合并成一个范围,然后直接解释成
long long 型的, 然后后面的这个也还是一样,那么这个什么意思呢?我们看一个例子,然后我们能够明白
这里面的这个21474836 48是等于2的31次方,也就是这边的2的31次方,
我们这个把它展开成写成直接写成
十进制,个十百千这样的一种形式的话,不是写成 2的多少次方这种形式的话,它展开成是这样一个数据,
后面我们来看一个例子,这个我们要例子当中
用到的是这个范围里面的数据,我们实际上也就是这个值,我们例子当中来看看
这样的一个常数,C语言当中如果定义了这一个常数, 然后在C90和C99里面,它是怎样解析的?
对于这个表达式,C语言程序当中,如果有这么一个表达式,
那么编译器编译的时候,它把这个负号和后面这个字面量
是分开来处理的, 编译器会分开来处理,实际上后面的这一个
字面量2147483648,首先它是构造成一个 有限状态,那么实际上就是构造成一个数字
串,然后把这个数字串再转换成0/1序列,转换成二进制,
然后要对这个数字串进行说明,要把它 的类型进行解析它的类型,把它说明成是
带符号数呢,还是无符号数,这样我们去运算的时候,比如说我们去做小于这种判断
这种运算实际上是用做减法去判断的,做减法判断的时候我们才
可以知道到底是按无符号数来比,还是按有符号数来比,
只有我们对这一个表达式当中的所有的 常数,比如说左边的这一个常数和右边的这一个常数,
确定了它的类型以后,我们才能确定这一个比较是按什么类型比,
因此编译器需要对这一个字面量来确定它的类型,
那么确定类型的时候,按照刚才C90的这个规则, 就是2147483648
它是等于2的三十 一次方,因为这边的负号是另外处理的,
好,2的31次方我们刚才看到在C90的时候, 它是解释成unsigned int,也就是它是一个无符号数,
而右边的这个是2的31次方减1,还在 int那个范围内,左边是一个无符号数,右边是一个带符号数,
那么这样的话,在一个表达式里面,有无符号数,有带符号数的时候,
它就完全是按照无符号数去比,而按照无符号数去比的话,那很显然左边
的数就是一个很大的数,所以 最后看上去是一个这个应该是一个true的这个结果,
但是运行以后,它的结果是false,这是在C90这个
系统上面是这样的,但是如果我们把这一个
左边这个赋给一个变量,这个变量是一个带符号数,
int型的,然后再去比,那显然左边和右边都是带符号数,
这时候,按照带符号数比的话,左边是一个负数,右边是一个正数,
那很显然负数小于正数,所以结果是true,
那如果我们把这个表达式写成左边的这个值我们写成这样的形式,
写成这样的形式,然后编译器再去处理的时候,这个负号是专门处理的, 然后处理这个这个字面量的时候,
很显然它是2的31次方减1, 所以它是在这个带符号数的那个
范围内,因此,左边的这一个是一个带符号数,右边也是带符号数, 按照带符号数比,那它的结果当然是true
负数小于正数,所以我们可以看出 最后的这个结果就是在C90下面,因为
这一个是2的31次方,被解释成了unsigned int
所以这个就按无符号数来比,结果
左边的比右边的大,左边的这个机器数,这个值的机器数就是10000
右边的这个机器数就是011111,这个就大家就能理解了,那么在C99的标准下面,
这个2的31次方,我们刚才看到它是被解释成 long
long型的, 因此都是左边右边都是带符号数,所以左边的这一个
机器数比右边的这个机器数要小,左边它是一个 负数,高位是1
,右边的高位是0,负数比正数小, 所以是true,那么后面我们讲过
i如果是int型的话,那i int型也是true,如果不这样的话,也是true 在这个地方比较的时候,我们讲过实际上有
无符号数和带符号数的时候,我们按照C语言的这个
规则,去把它解释整个表达式是按照无符号数来计算的。
那么这一个地方,如果都是C99,下面都是带符号数的话,那它全部按带符号数来比,
好,最后我们再看一个例子,这个例子当中,
就是前面有个例子我们已经说明了,这个这个
然后这边的话是,左边是这个值,右边是这个值,也就是刚才的那个例子
很显然,最后打印出来的这个结果,这边的这个x应该是等于
按照无符号数,它是等于一个最大的 一个很大的一个值。
按照负数的话它就是负1,这个值按照无符号数
的话,它就是本身,就是它,按照带符号数的话,那它就是一个
最小的负数,那就是负的2147483648
然后这个去比的时候,它和它比的时候,很显然 在c90上面,它是一个
解释成无符号数,所以按无符号数比的话,左边是一个 很大的数,左边的数比右边的数大。
所以打印出来的应该是后面的 这个,这个,那么如果把这个
它减,就是这个,这两个数来比的时候 很显然它也是无符号数,按无符号数来比
按无符号数来比的话,实际上最终的这个结果 左边是应该等于,左边
这个值我们知道,它的机器数是1,后面
是三十一个 0,三十一个0,然后再减1
那么应该是等于什么呢?左边,这个应该是等于0
11,三十一个1,我们就把这一位上面减1,不够减就是1
前面都不够减,都是1,第一位原来都是1,然后就变成了0,所以左边的值是
这个,然后显然这个值 对应的机器数也是011
因为这个值实际上是等于
2的31次方减1,2的31次方的机器数就等于它
因此,比较这两个数的时候
它和它应该是相等的
也就是说,最后的这个,这个条件是不满足,所以不会打印出来
然后就比这个的时候,肯定是相等的,所以最后打印出来的这个值 应该是,执行的结果应该是它
那C90上的运行的结果就是我们刚才讲过的
这个x是在机器里面是等于负1的机器数就是
32个1,32个1就等于2的32次方减1 2的32次方减1的值就等于它
然后按照这个带符号数来显示的话,它原来是负1,所以这儿还是负1
然后这个u是机器数 这个无符号数的机器数我们以前讲过了
实际上它是等于2的
31次方,等于2的31次方,所以它的机器数应该是等于
1后面31个0
那么所以它打印出来的这个无符号数的值还是它
但是如果把这个数解释成 带符号数的话,解释成补码的话,那它就是一个负数
负的个位取反,末位加1还是负的
31次方,负的31次方就是等于 负的2147483648
所以这边这个值u 这个u用带符号数去
打印的时候,打印出来的结果就是它 这个地方我们刚才已经解释了,很显然这个值
看上去是小于它,因为它是一个无符号数,所以是 它其实是大于它的。
因此打印出来的这个结果应该是这个结果
打印出来的是false,最后一个打印 出来的应该是这个结果。
这是C90上面的运行的 结果,那么C99上面是怎样的呢?大家可以回去试一试
打印出来的结果,后面两个就不一样了,就是后面这两个应该是
不一样的
[音乐]