当前位置: C语言 -- 基础 -- 转换

转换(二)

4、浮点类型间的相互转换

实数浮点类型值转换成另一种实数浮点类型时,如果转换值在新类型中可以准确表示,则值保持不变。

实数浮点类型值转换成标准浮点类型时,如果转换值在新类型的值域范围内,但不能准确表示,转换结果是最接近的较高可表示值,还是最接近的较低可表示值,将由实现定义。如果转换值在新类型可表示的值域范围外,其行为是未定义的。

实数浮点类型值转换成十进制浮点类型时,如果转换值在新类型中不能准确表示,应按ISO/IEC 60559标准对结果进行正确舍入,并抛出异常。


复数类型值转换成另一个复数类型时,实部和虚部都遵循相应实数类型的转换规则。

实数类型值转换成复数类型时,复数结果值的实数部分根据相应实数类型的转换规则进行转换,复数结果值的虚数部分为正0或者无符号0。复数类型值转换成除bool类型外的实数类型时,复数类型值的虚数部分被丢弃,实数部分值根据相应实数类型的转换规则进行转换。

double complex dc = 0.5 + 1.0I;
double d;

d = dc;
dc = 3.14;

printf("d = %.2f\n", d);				//输出d = 0.50。
printf("dc = %.2f%+.2fI\n", creal(dc),cimag(dc));	//输出dc = 3.14+0.00I

5、实数浮点类型与整数类型间的相互转换

标准浮点类型的有限值转换成除bool类型外的整数类型时,小数部分将被丢弃(即值向0截取)。

unsigned ui;
ui = 3.14f;     //ui值为3。

signed si;
si = -3.14f;    //si值为-3。

如果标准浮点类型值的整数部分不能使用整数类型表示,其行为是未定义的。标准浮点类型值转换成无符号整数类型时,如果标准浮点类型值的整数部分不能使用无符号整数类型表示,实现无需执行加减模的操作,因此当标准浮点类型值在(-1Utype_MAX + 1)区间内(:Utype_MAX是对应无符号整数类型可表示的最大值。),程序具有较好的可移植性。

unsigned char uc;

uc = 257.14f;   //编译时会给出警告,uc值为255。
uc = -3.14f;    //编译时会给出警告,uc值为0。

上述代码使用GCC编译。


十进制浮点类型的有限值转换成除bool类型外的整数类型时,小数部分将被丢弃(即值向0截取)。如果十进制浮点类型值的整数部分不能使用整数类型表示,应抛出"invalid"浮点异常,转换结果是未指定的。


整数值转换成标准浮点类型时,如果转换值在新类型中可以准确表示,则值保持不变。如果转换值在新类型中可以表示,但不能准确表示,转换结果是最接近的较高可表示值,还是最接近的较低可表示值,将由实现定义。如果整数值在标准浮点类型可表示的值域范围外,其行为是未定义的。

float f;

f = 25;         //f的值为25.000000。
f = 0X1000001;  //f的值为16777216.000000。

整数0X1000001,即16777217,最低位的1使用float类型无法准确表示;实现选择了最接近的较低可表示值。


整数值转换成十进制浮点类型时,如果转换值在新类型中可以准确表示,则值保持不变。如果转换值在新类型中不能准确表示,应按ISO/IEC 60559标准对结果进行正确舍入,并抛出异常。


6、常用算术转换

许多运算符希望算术操作数发生转变,产生与结果相同的类型,目的是确定操作数和结果的共同实数类型(common real type)。对于指定的操作数,每个操作数在不改变类型域的情况下转换成共同实数类型。除非另有明确说明,否则共同实数类型也是结果对应的实数类型,如果操作数相同,结果类型域为操作数的类型域;否则为复数。这种模式称为常用算术转换(usual arithmetic conversions)。


常用算术转换的规则:

如果一个操作数是十进制浮点类型,另一个操作数不能是标准浮点类型、复数类型或者虚数类型。

如果一个操作数是_Decimal128类型,另一个操作数将转换成_Decimal128类型;

否则,如果一个操作数是_Decimal64类型,另一个操作数将转换成_Decimal64类型;

否则,如果一个操作数是_Decimal32类型,另一个操作数将转换成_Decimal32类型;

否则,如果一个操作数对应的实数类型是long double类型,另一个操作数在不改变类型域的情况下转换成long double类型;

否则,如果一个操作数对应的实数类型是double类型,另一个操作数在不改变类型域的情况下转换成double类型;

否则,如果一个操作数对应的实数类型是float类型,另一个操作数在不改变类型域的情况下转换成float类型;

#define TYPE(x) _Generic((x),				\
              float: "float type",			\
              double: "double type",			\
              float complex: "float complex",		\
              double complex: "double complex",	\
              default: "unknown type"			\
              )
...
double complex dc = 0.5 + 1.0I;
float f = 3.0f;

printf("%s\n", TYPE(dc+f));   //输出double complex。

变量f的类型由float类型转变成double类型,然后和变量dc相加,表达式dc+f的结果类型是double complex类型。


否则,如果两种类型中的任一类型是枚举类型,则将其转换成底层类型(underlying type);

然后,对操作数执行整数提升(integer promotions);以下规则适用于提升后的操作数:

-- 如果两个操作数具有相同类型,则不需要进一步转换;

-- 否则,如果两个操作数都是有符号整数类型或者都是无符号整数类型,具有较低整数转换等级类型的操作数将转换成具有较高整数转换等级操作数的类型;

signed i = 5;
signed long l = 10;

表达式i+li将转换成signed long类型,表达式的类型是signed long类型。


-- 否则,如果无符号整数类型操作数的整数转换等级大于或者等于另一操作数的整数转换等级,有符号整数类型的操作数将转换成无符号整数类型;

signed i = -5;
unsigned long ul = 10;

表达式i+uli将转换成unsigned long类型,表达式的类型是unsigned long类型。


-- 否则,如果有符号整数类型操作数的类型可以表示无符号整数类型操作数类型的所有值,无符号整数类型的操作数将转换成有符号整数类型操作数的类型;

signed long l = -5;
unsigned u = 10;

表达式l+uu将转换成signed long类型,表达式的类型是signed long类型。


-- 否则,两个操作数都将转换成与有符号整数类型操作数的类型对应的无符号整数类型。


浮点操作数的值和浮点表达式的结果值可能以比其类型更大的范围和精度表示;但类型不会因此改变。