C语言非常道
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

4.6.2 整数—整数转换

在C语言里,不同的类型决定了可以表示的数值范围,以及数值在存储器中如何表示,以什么样的位模式存在。变量是有类型的,从变量中读出的值也是有类型的,这个值的类型和变量的类型一致。

相应地,往变量写入一个值,值的类型应该和变量的类型一致。如果值的类型和变量的类型不一致,则必须先转换为变量的类型但有些类型之间是不允许转换的。,请看下面的例子。

              /******c0406.c******/
              int main(void)
              {
                  int m = 3700U;
                  unsigned int u = m;
                  signed char sc;
                  unsigned char uc;
                  uc = u;
                  sc = u;
                  sc = 107LL;
              }

在这里,整型常量3700U的确切类型是unsigned int(对照表4-2),但变量m的类型是int,这就要将3700U从unsigned int转换为int之后才能初始化。

在所有整数类型中,_Bool类型最特殊,先来看它。C语言规定,将任何整数类型的值转换为_Bool类型时,零值转换为0,非零值转换为1;将一种整数类型的值转换为_Bool之外的整数类型时,如果这个值可以用新类型表示,则转换后的值同原值相比不变。

在这里,3700U的类型是unsigned int,但是int类型的取值范围里也有3700这个数,所以3700U是可以用int类型来表示的,于是它自动转换为int类型的3700并用于初始化变量m。

接下来,变量u的类型是unsigned int,但其初始化器为左值m,经左值转换后得到一个int类型的值3700。这个3700可以用unsigned int类型来表示,故又从int类型转换为unsigned int类型并用于初始化变量u。

再往下,我们声明了变量uc和sc,并将变量u的值赋给它们。凭直觉,这个赋值是有问题的,因为变量u的值是unsigned int类型的3700,而变量uc和sc的类型分别是unsigned char和signed char,应该是无法容纳的。

C语言规定,将任何一种整数类型的值转换为非_Bool的另一种无符号整数类型时,如果无法用新类型来表示,则转换的方法是将这个值重复地加上或者减去比新类型所能表示的最大值大1的数,直到结果可以用新类型来表示;将任何一种整数类型的值转换为另一种有符号整数类型时,如果这个值无法用新类型来表示,则转换的结果取决于C实现。

在我的机器上,unsigned char类型可以表示的最大值是255,所以,变量uc不能表示变量u的值3700。在这种情况下,我们不停地用变量u的值减去256,直到结果小于或者等于255。在做14次相减后,结果是3700-14×256=116。所以,变量uc在赋值之后的结果是116。

但是,在将变量u的值赋给变量sc后,变量sc的结果不确定,这要取决于C实现如何将unsigned int类型的3700转换为signed char类型。

最后,107LL的类型是signed long long int,变量sc的类型是signed char,但signed char类型的取值范围里也有107,也就是可以表示,故,将107LL转换为signed char类型并赋给变量sc后,变量sc的值是107。

练习4.7

若某无符号整数类型可表示的最大值为M,那么,把-1赋给这种类型的变量后,该变量的值是什么?