发生了什么类型的转换?

#include "stdio.h" int main() { int x = -13701; unsigned int y = 3; signed short z = x / y; printf("z = %d\n", z); return 0; } 

我希望答案是-4567。 我得到“z = 17278”。 为什么推广这些数字导致17278?

我在Code Pad中执行了这个。

隐藏类型转换是:

 signed short z = (signed short) (((unsigned int) x) / y); 

混合有符号和无符号类型时,未签名的类型会赢。 x被转换为unsigned int ,除以3,然后将该结果下转换为(signed) short 。 使用32位整数:

 (unsigned) -13701 == (unsigned) 0xFFFFCA7B // Bit pattern (unsigned) 0xFFFFCA7B == (unsigned) 4294953595 // Re-interpret as unsigned (unsigned) 4294953595 / 3 == (unsigned) 1431651198 // Divide by 3 (unsigned) 1431651198 == (unsigned) 0x5555437E // Bit pattern of that result (short) 0x5555437E == (short) 0x437E // Strip high 16 bits (short) 0x437E == (short) 17278 // Re-interpret as short 

顺便说一句, signed关键字是不必要的。 signed short是一种较长的说short 。 唯一需要显式signed类型是charchar可以根据平台签名或签名; 默认情况下,所有其他类型始终签名。

简短回答:该部门首先将x提升为unsigned 。 只有这样才能将结果转回signed short

答案很长:读这个SO线程。

问题来自unsigned int y 。 实际上, x/y变为无符号。 它适用于:

 #include "stdio.h" int main() { int x = -13701; signed int y = 3; signed short z = x / y; printf("z = %d\n", z); return 0; } 

每次在加法和乘法算术运算中混合“大”有符号和无符号值时,无符号类型“获胜”,并且在无符号类型的域中执行求值(“大”表示int和更大)。 如果您的原始签名值为负数,则首先会根据签名到无符号转换的规则将其转换为正无符号值。 在您的情况下-13701将变为UINT_MAX + 1 - 13701 ,结果将用作被除数。

请注意,在典型的32位int平台上进行有符号无符号转换的结果将导致无符号值4294953595 。 除以3你会得到1431651198 。 此值太大,无法强制进入16位short类型平台上的short对象。 尝试这样做会导致实现定义的行为。 因此,如果您的平台的属性与我的假设相同,那么您的代码会产生实现定义的行为。 从forms上讲,您获得的“无意义” 17278值只不过是该实现定义行为的特定表现forms。 有可能,如果您编译了启用了溢出检查的代码(如果您的编译器支持它们),它将陷入分配。