#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中执行了这个。
#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
是char
. char
可以根据平台签名或不签名;默认情况下,所有其他类型始终签名。
简短的回答:该部门首先x
升级为unsigned
. 只有这样,结果才会被转换回 a 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
平台上的有符号到无符号转换的结果将产生 unsigned value 4294953595
。除法后3
你会得到1431651198
. 此值太大,无法short
在 16 位short
类型的平台上强制转换为对象。尝试这样做会导致实现定义的行为。因此,如果您的平台属性与我的假设相同,那么您的代码会产生实现定义的行为。从形式上讲,17278
您获得的“无意义”值只不过是实现定义的行为的特定表现。如果您在启用溢出检查的情况下编译代码(如果您的编译器支持它们),它可能会陷入分配。