当前位置:嗨网首页>书籍在线阅读

23-类型转换

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

5.5 类型转换

通常,在语句和表达式中应使用类型相同的变量和常量。但是,如果使用混合类型,C不会像Pascal那样停在那里死掉,而是采用一套规则进行自动类型转换。虽然这很便利,但是有一定的危险性,尤其是在无意间混合使用类型的情况下(许多UNIX系统都使用lint程序检查类型“冲突”。如果选择更高错误级别,许多非UNIX C编译器也可能报告类型问题)。最好先了解一些基本的类型转换规则。

1.当类型转换出现在表达式时,无论是 unsigned 还是 signedcharshort 都会被自动转换成 int ,如有必要会被转换成 unsigned int (如果 shortint 的大小相同, unsigned short 就比 int 大。这种情况下, unsigned short 会被转换成 unsigned int )。在K&R那时的C中, float 会被自动转换成 double (目前的C不是这样)。由于都是从较小类型转换为较大类型,所以这些转换被称为升级(promotion)。

2.涉及两种类型的运算,两个值会被分别转换成两种类型的更高级别。

3.类型的级别从高至低依次是 long doubledoublefloatunsigned long longlong longunsigned longlongunsigned intint 。例外的情况是,当 longint 的大小相同时, unsigned intlong 的级别高。之所以 shortchar 类型没有列出,是因为它们已经被升级到 intunsigned int

4.在赋值表达式语句中,计算的最终结果会被转换成被赋值变量的类型。这个过程可能导致类型升级或降级(demotion)。所谓降级,是指把一种类型转换成更低级别的类型。

5.当作为函数参数传递时, charshort 被转换成 intfloat 被转换成 double 。第9章将介绍,函数原型会覆盖自动升级。

类型升级通常都不会有什么问题,但是类型降级会导致真正的麻烦。原因很简单:较低类型可能放不下整个数字。例如,一个8位的 char 类型变量存储整数 101 没问题,但是存不下 22334

如果待转换的值与目标类型不匹配怎么办?这取决于转换涉及的类型。待赋值的值与目标类型不匹配时,规则如下。

1.目标类型是无符号整型,且待赋的值是整数时,额外的位将被忽略。例如,如果目标类型是8位 unsigned char ,待赋的值是原始值求模 256

2.如果目标类型是一个有符号整型,且待赋的值是整数,结果因实现而异。

3.如果目标类型是一个整型,且待赋的值是浮点数,该行为是未定义的。

如果把一个浮点值转换成整数类型会怎样?当浮点类型被降级为整数类型时,原来的浮点值会被截断。例如, 23.1223.99 都会被截断为 23-23.5 会被截断为 -23

程序清单5.14演示了这些规则。

程序清单5.14  convert.c 程序

/* convert.c -- 自动类型转换 */
#include <stdio.h>
int main(void)
{
     char ch;
     int i;
     float fl;
     fl = i = ch = 'C';                                    /* 第9行  */
     printf("ch = %c, i = %d, fl = %2.2f\n", ch, i, fl);   /* 第10行 */
     ch = ch + 1;                                          /* 第11行 */
     i = fl + 2 * ch;                                      /* 第12行 */
     fl = 2.0 * ch + i;                                    /* 第13行 */
     printf("ch = %c, i = %d, fl = %2.2f\n", ch, i, fl);   /* 第14行 */
     ch = 1107;                                            /* 第15行 */
     printf("Now ch = %c\n", ch);                          /* 第16行 */
     ch = 80.89;                                           /* 第17行 */
     printf("Now ch = %c\n", ch);                          /* 第18行 */
     return 0;
}

运行 convert.c 后输出如下:

ch = C, i = 67, fl = 67.00
ch = D, i = 203, fl = 339.00
Now ch = S
Now ch = P

在我们的系统中, char 是8位, int 是32位。程序的分析如下。

  • 第9行和第10行:字符 'C' 被作为1字节的ASCII值存储在 ch 中。整数变量 i 接受由 'C' 转换的整数,即按4字节存储 67 。最后, fl 接受由 67 转换的浮点数 67.00
  • 第11行和第14行:字符变量 'C' 被转换成整数 67 ,然后加 1 。计算结果是4字节整数 68 ,被截断成1字节存储在 ch 中。根据 %c 转换说明打印时, 68 被解释成 'D' 的ASCII码。
  • 第12行和第14行: ch 的值被转换成4字节的整数( 68 ),然后 2 乘以 ch 。为了和 fl 相加,乘积整数( 136 )被转换成浮点数。计算结果( 203.00f )被转换成 int 类型,并存储在 i 中。
  • 第13行和第14行: ch 的值( 'D' ,或 68 )被转换成浮点数,然后 2 乘以 ch 。为了做加法,i的值( 203 )被转换为浮点类型。计算结果( 339.00 )被存储在 fl 中。
  • 第15行和第16行:演示了类型降级的示例。把 ch 设置为一个超出其类型范围的值,忽略额外的位后,最终 ch 的值是字符 S 的ASCII码。或者,更确切地说, ch 的值是 1107 % 256 ,即 83
  • 第17行和第18行:演示了另一个类型降级的示例。把 ch 设置为一个浮点数,发生截断后, ch 的值是字符 P 的ASCII码。