C 语言类型转换
将字符类型转换为整型时,我们需要注意一点。C 语言没有指定 char 类型的变量是无符号变量(signed)还是带符号变量(unsigned)。当把一个 char 类型的值转换为 int 类型的值时,其结果有没有可能为负数?对于不同的机器,其结果也不同,这反映了不同机器结构之间的区别。在某些机器中,如果 char 类型值的最左一位为 1,则转换为负整数(进行“符号扩展”)。而在另一些机器中,把 char 类型值转换为 int 类型时,在 char 类型值的左边添加 0,这样导致的转换结果值总是正值。
C 语言的定义保证了机器的标准打印字符集中的字符不会是负值,因此,在表达式中这些字符总是正值。但是,存储在字符变量中的位模式在某些机器中可能是负的,而在另一些机器上可能是正的。为了保证程序的可移植性,如果要在 char 类型的变量中存储非字符数据,最好指定 signed 或 unsigned 限定符。
C 语言中,很多情况下会进行隐式的算术类型转换。一般来说,如果二元运算符(具有两个操作数的运算符称为二元运算符,比如+或*)的两个操作数具有不同的类型,那么在进行运算之前先要把“较低”的类型提升为“较高”的类型。运算的结果为较高的类型。但是,如果没有 unsigned 类型的操作数,则只要使用下面这些非正式的规则就可以了。
- 如果其中一个操作数的类型为 long double,则将另一个操作数转换为 long double 类型;
- 如果其中一个操作数的类型为 double,则将另一个操作数转换为 double 类型;
- 如果其中一个操作数为 float,则将另一个操作数转换为 float 类型;
- 将 char 与 short 类型的操作数转换为 int 类型;
- 如果其中一个操作数的类型为 long,则将另一个操作数也转换为 long 类型。
注意,表达式中 float 类型的操作数不会自动转换为 double 类型,这一点与最初的定义有所不同。一般来说,数学函数(如标准头文件 <math.h>的定义的函数)使用双精度类型的变量。使用 float 类型主要是为了在使用较大的数组时节省存储空间,有时也为了节省机器执行时间(双精度算术运算特别费时)。
当表达式中包含 unsigned 类型的操作数时,转换规则要复杂一些。主要原因在于,带符号值与无符号值之间的比较运算与机器相关的,因为它们取决于机器中不同整数类型的大小。例如,假定 int 类型占 16 位,long 类型占 32 位,那么,-1L>1U,这是因为 unsigned int 类型的 1U 将被提升位 signed long 类型;但 -1L>1UL,这是因为 -1L 将被提升为 unsigned long 类型,因而成为一个比较大的正数。
由于函数调用的参数是表达式,所以在把参数传递给函数时也可能进行类型转换。在没有函数原型的情况下,char 与 short 类型都将被转换为 int 类型,float 类型将被转换为 double 类型。因此,即使调用函数的参数为 char 或 float 类型,我们也把参数声明为 int 或 double 类型。
最后,在任何表达式中都可以使用一个称为强制类型转换的一元运算符强制进行显示的类型转换。在下列语句中,表达式将按照上述转换规则被转换为类型名指定的类型:
(类型名)表达式
我们可以这样来理解强制类型转换的准确含义:在上述语句中,表达式首先被赋值给类型名指定的类型的某个变量,然后再用该变量替换上述整条语句。