未签名的签名转换

时间:2011-04-27 07:48:01

标签: c++

请考虑以下事项:

#include <iostream>

int main() {

    unsigned int x = 3;
    unsigned int y = 5;

    std::cout << "a: " << x - y        << std::endl;

    std::cout << "b: " << ((int)x) - y << std::endl;

    std::cout << "c: " << x - ((int)y) << std::endl;

    std::cout << "d: " << ((int)x) - ((int)y) << std::endl;

}

$ g++ -Wconversion -Wall uint_stackoverflow.cc -o uint_stackoverflow && ./uint_stackoverflow
a: 4294967294
b: 4294967294
c: 4294967294
d: -2

我理解为什么“a”没有给出预期的结果。但为什么“b”和“c”失败让我感到困惑。对于“b”,我认为在将“x”转换为“int”后,结果将再次为“int”。

你能告诉我吗?

编辑:编译器不应该发出警告吗? g ++(Ubuntu / Linaro 4.4.4-14ubuntu5)4.4.5

谢谢,

有人

3 个答案:

答案 0 :(得分:26)

在算术运算中,如果任何操作数为unsigned,则其他操作数将转换为unsigned(如果其signed),并且结果为操作也将unsigned

此外,将unsigned强制转换为signed然后执行操作不会更改操作数的位表示形式。在二进制补码架构上(即几乎每个现代架构),(int)x具有与x相同的位表示,只有它们的解释在计算值时才会改变十进制。但重要的是,算术运算是在位表示上执行的( <十字系统中的)。并且由于转换不会改变位表示,结果的位表示也不会改变。

C ++ 03标准在§5/ 9中说:

  

许多期望的二元运算符   算术或枚举的操作数   类型导致转换和产量   结果类型以类似的方式。该   目的是产生一个共同的类型,   这也是结果的类型。   这种模式通常被称为   算术转换,是   定义如下:

     

[...]

     

否则,如果任一操作数为   未签名,另一个应转换   未签名

答案 1 :(得分:10)

像往常一样引用标准......

对于C ++ 98,§[expr] / 9:

  

许多期望的二元运算符   算术或枚举的操作数   类型导致转换和产量   结果类型以类似的方式。该   目的是产生一个共同的类型,   这也是结果的类型。   这种模式通常称为   算术转换,它们是   定义如下:

     
      
  • 如果任一操作数的类型为long double,则另一个操作数将被转换   到long double
  •   
  • 否则,如果任一操作数为double,则另一个操作数将被转换   到double
  •   
  • 否则,如果任一操作数为float,则另一个操作数将被转换   到float
  •   
  • 否则,应对两者进行整体促销(4.5)   操作数。 54)
  •   
  • 然后,如果任一操作数为unsigned long,则另一个操作数将转换为   unsigned long
  •   
  • 否则,如果一个操作数是long int而另一个是unsigned int,   那么long int可以代表所有人   一个unsigned int的值,   unsigned int应转换为   long int;否则两个操作数   应转换为unsigned long int
  •   
  • 否则,如果任一操作数为long,则另一个操作数将被转换   到long
  •   
  • 否则,如果任一操作数为unsigned,则另一个操作数为unsigned   已转换为int
  •   
     

[注:否则,唯一剩下的   case是两个操作数都是long double]

基本上,它可以概括为

  • double&gt; float&gt; unsigned long&gt; long&gt; unsigned&gt; int&gt; int
  • (小于int的类型将转换为int

在第5项之后,对于C ++ 0x(§[expr] / 10)更改了文本,但对OP代码的影响是相同的:unsigned将转换为{{1}} }。

答案 2 :(得分:3)

这是因为在执行隐式转换时存在数据类型的层次结构,无符号整数的优先级高于有符号整数,因此b和c将被转换为无符号整数,这就是为什么你看到的结果。< / p>

如果您不确定类型但知道所需结果的类型,那么您应该像在d中那样投射x和y。

这对类型转换有一个非常好的解释:

http://www.learncpp.com/cpp-tutorial/44-type-conversion-and-casting/