c中的类型提升和转换

Type promotion and conversion in c

double dVal;
int iVal = -7;
unsigned long ulVal = 1000;
dVal = iVal * ulVal;
printf("iVal * ulVal = %lf\n", dVal);

有人可以一步步解释如何获得 4294960296.000000 吗?

参考 Joachim 提到的 http://en.cppreference.com/w/c/language/conversion

首先发生两个整数的乘法。然后将结果存储在浮点数中。

所以我们看iVal * ulVal。这里我们参考普通算术转换部分。两个操作数都是整数,所以情况 4。适用。

首先发生 整数促销。在此,两个操作数都是整数或更大,因此它们没有变化。

If the types after promotion are the same, that type is the common type

这不适用,因为类型分别是 int 和 unsigned long。

Otherwise, if both operands after promotion have the same signedness (both signed or both unsigned), the operand with the lesser conversion rank (see below) is implicitly converted to the type of the operand with the greater conversion rank

这也不适用,因为一种类型是有符号的,第二种是无符号的

Otherwise, the signedness is different: If the operand with the unsigned type has conversion rank greater or equal than the rank of the type of the signed operand, then the operand with the signed type is implicitly converted to the unsigned type

这里无符号操作数为long,有符号操作数为int,long的秩大于int,所以这部分适用。 signed int 转换为 unsigned long。

因此,我们有两个数字 4294967289(unsigned long)和 1000(unsigned long)的乘法。做乘法会有溢出,但如果你计算 4294967289000 % 2^32,你会得到 4294960296.

然后在等号处将其转换为浮点数,然后打印出来。

真的很简单:

iVal 从 int 提升为 unsigned long。因此它的值 -7(作为二进制补码)变为正值 0xFFFFFFF9(即 4294967289)(至少在您的特定系统上)。

当乘以 1000 时,unsigned long 会溢出,因此结果不是 4,294,967,289,000 (0x3E7 FFFF E4A8),而是 0xFFFFE4A8 (429960296)。

然后将其转换为双精度数,得到您的最终答案。尾随零是因为 float 的值略高于 429960296,因为它是由 printf 四舍五入到 6 位数的分数之和构成的。