2
#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中执行了这个。

4

4 回答 4

11

隐藏的类型转换是:

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。唯一需要显式的类型signedchar. char可以根据平台签名或不签名;默认情况下,所有其他类型始终签名。

于 2010-09-23T15:27:33.067 回答
4

简短的回答:该部门首先x升级为unsigned. 只有这样,结果才会被转换回 a signed short

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

于 2010-09-23T15:26:16.567 回答
3

问题来自于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;
}
于 2010-09-23T15:27:31.697 回答
1

每次在加法和乘法算术运算中混合“大”有符号和无符号值时,无符号类型“获胜”并且在无符号类型的域中执行评估(“大”意味着int更大)。如果你原来的有符号值是负数,它首先会按照有符号到无符号转换的规则转换为正无符号值。在你的情况下-13701会变成UINT_MAX + 1 - 13701,结果将被用作股息。

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

于 2010-09-23T16:19:40.300 回答