发生了什么类型的转换?

时间:2010-09-23 15:23:59

标签: c type-conversion promotions

#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 个答案:

答案 0 :(得分:10)

隐藏类型转换为:

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

混合有符号和无符号类型时,未签名的类型会赢。 x转换为unsigned int除以3,然后将该结果下转换为(已签名)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可以根据平台签名或签名;默认情况下,所有其他类型始终是签名的。

答案 1 :(得分:4)

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

答案很长:阅读this SO thread.

答案 2 :(得分: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;
}

答案 3 :(得分:1)

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

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