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 吗?
- 先到先得,将 iVal 的符号更改为未签名或提升
在与 ulVal 相乘之前转换为 ulVal 类型?
- 此外,如果我们将 iVal 和 ulVal 相乘,我们就超出了 long 类型的范围
然后我们将该乘法值存储到 double 变量中(因此我们进行了转换
再次)。但是当双类型时,我们如何知道要舍入到哪个值
是 0 附近最精确的,我们从 0 开始的距离
相邻数字之间更大?
参考 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 位数的分数之和构成的。
double dVal;
int iVal = -7;
unsigned long ulVal = 1000;
dVal = iVal * ulVal;
printf("iVal * ulVal = %lf\n", dVal);
有人可以一步步解释如何获得 4294960296.000000 吗?
- 先到先得,将 iVal 的符号更改为未签名或提升 在与 ulVal 相乘之前转换为 ulVal 类型?
- 此外,如果我们将 iVal 和 ulVal 相乘,我们就超出了 long 类型的范围 然后我们将该乘法值存储到 double 变量中(因此我们进行了转换 再次)。但是当双类型时,我们如何知道要舍入到哪个值 是 0 附近最精确的,我们从 0 开始的距离 相邻数字之间更大?
参考 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 位数的分数之和构成的。