C语言的转换

来源:互联网 发布:104cm肛塞淘宝 编辑:程序博客网 时间:2024/04/24 21:52

先上题目

#include <stdio.h>int main(void){    unsigned char a = 0xff;    char b = 0xff;    int c = a==b; // true, or false?    printf("C: %d\n",c);}
输出是什么?

其实不是1而是0!

解析:

如果int能够表示原始类型中的所有数值,那么这个数值就被转成int型,否则,它被转成unsigned int型。这种规则被称为整型提升。所有其它类型都不会被整型提升改变。
可以看出有符号或者无符号的char、short都可以被signed int表示,所以当它们作算术运算时,都会被转成signed int。 
在前面的例子中, unsigned char a = 0xff 的值是255。但是, char b = 0xff 的值是-1。当它们都被转为int类型时,a 仍然是255,即 0x000000ff, 而b却变成0xffffffff ,代表整型中的-1。以下代码可以证明:

#include <stdio.h>int main(void){    unsigned char a = 0xff;    char b = 0xff;    printf("A: %08x, B: %08x\n", a, b);    return 0;}

输出结果是:
A: 000000ff, B: ffffffff

下面就对转换进行一次深刻的理解:

转换:根据操作数的不同,某些运算符会引起操作数的值从某种类型转换为另一种类型。

1.整形提升

在一个表达式中,凡是可以使用整形的地方都可以使用带符号或无符号的字符、短整形或整形字段,还可以使用枚举类型的对象。如果原始类型的所有值都可以用int类型表示,则其值将转换为int类型;否则将被转换为unsigned int 类型。这一过程称为整形提升。

2.整形转换

将任何整数转换为某种指定的无符号类型数的方法是:以该符号类型能够表示的最大值加1为模,找出与此整数同余的最小非负值。在对二的补码表示中,如果该无符号类型的位模式较窄,这就相当于左截取;如果该无符号类型的位模式较宽,这就相当于对带符号值进行符号扩展和对无符号值进行0填充。

将任何整数转换为带符号类型时,如果它可以在新类型中表示出来,则其值保持不变,否则它的值同具体的实现有关。

对带符号值进行符号扩展                                                                                     对无符号值进行0填充


3.整数和浮点数

当把浮点类型的值转化为整时,小数部分将被丢弃。如果结果值不能用整表示,则其行为是未定义的。特别是,将负的浮点数转换为无符号整的结果是没有定义的。

当把整型值转换为浮点类型时,如果该值在浮点类型可表示的范围内但不能精确表示,则结果可能是下一个较高或较低的可表示值。如果该值超出可表示的范围,则其行为是未定义的。

4.浮点类型

将一个精度较低的浮点值转化为相同或更高精度的浮点类型时,它的值保持不变。将一个较高精度的浮点类型值转换为较低精度的浮点类型时,如果它的值在可表示范围内,则结果可能是下一个较高或较低的表示值。如果结果在可表示范围之外,则其行为是未定义的。

低精度--->高精度


高精度---->低精度


5.算术类型转换

许多运算符都会以类似的方式在运算过程中引起转换,并产生结果类型。其效果是将所有操作数转换为同一公共类型,并以此作为结果的类型。这种方式的转换称为普通算术类型转换。

首先,如果任何一个操作数为long double 类型,则将另一个操作数转换为long double 类型。

否则,如果任何一个操作数为double 类型,则将另一个操作数转换为double类型。

否则,如果任何一个操作数为float类型,则将另一个操作数转换为float类型。

否则,同时对两个操作数进行整形提升;然后,如果任何一个操作数为unsigned long int 类型,则将另一个操作数转化为unsigned long int 类型。

否则,如果一个操作数为long int类型且另一个操作数为unsigned int类型,则结果依赖于long int 类型是否可以表示所有的unsigned int 类型的值。如果可以,则将unsigned int 类型的操作数转换为long int ;如果不可以,则将两个操作数都转换为unsigned long int 类型。

否则,如果一个操作数为long int类型,则将另一个操作数转换为long int 类型。

否则,如果一个操作数为unsigned int 类型,则将另一个操作数转换为unsigned int 类型。

否则,将两个操作数都转换为Int 类型。

long double>double>float---进行整形提升--->unsigned long int>long int>unsigned int>int

注意:

第一,对于float类型操作数的算术运算可以只用单精度而不用双精度。

第二,当较短的无符号类型与较长的无符号类型一起运算时,不将无符号类型的属性传递给结果类型;

当一个无符号表达式与一个具有同样长度的带符号表达式相比较时,结果仍然是无法预测的。

(新规则虽然稍微复杂一些,但减少了无符号数与带符号数混合使用情况下的麻烦。from The C Programming Language Second Edition)

通常情况下,在对int类型的数值作运算时,CPU的运算速度是最快的。
在x86上,32位算术运算的速度比16位算术运算的速度快一倍。
C语言是一个注重效率的语言,所以它会作整型提升,使得程序的运行速度尽可能地快。
因此,你必须记住整型提升规则,以免发生一些整型溢出的问题。
转载注明出处

1 0
原创粉丝点击