未签名和签名的比较

时间:2010-08-02 04:03:20

标签: c++

这是非常简单的代码,

#include <iostream>
using namespace std;
int main() {
    unsigned int u=10;
    int i;
    int count=0;
    for (i=-1;i<=u;i++){
        count++;
    }
    cout<<count<<"\n";
    return 0;
}

count的值是0.为什么?

5 个答案:

答案 0 :(得分:8)

<=的两个操作数都必须提升为相同的类型。

显然他们被提升为unsigned int(我没有在我面前的标准规则,我会在一秒钟内查看)。由于(unsigned int)(-1) <= u为false,因此循环永远不会执行。

该规则载于标准第10段第5节(expr),其中指出(我已强调适用于此处的规则):

  

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

     
      
  • 如果任一操作数是作用域枚举类型(7.2),则不执行任何转换;如果另一个操作数的类型不同,则表达式格式不正确。
  •   
  • 如果任一操作数的类型为long double,则另一个操作数应转换为long double。
  •   
  • 否则,如果任一操作数为double,则另一个操作数应转换为double。
  •   
  • 否则,如果任一操作数为float,则另一操作数应转换为float。
  •   
  • 否则,应对两个操作数执行整体促销(4.5)。 60接下来   规则应适用于推广的操作数:
  •   
  • 如果两个操作数具有相同的类型,则无需进一步转换。
  •   
  • 否则,如果两个操作数都有有符号整数类型或两者都有无符号整数类型,则具有较小整数转换等级类型的操作数应转换为具有更高等级的操作数类型。
  •   
  • 否则,如果具有无符号整数类型的操作数的秩大于或等于另一个操作数的类型的等级,则带有符号整数类型的操作数应转换为带有无符号的操作数的类型整数类型。
  •   
  • 否则,如果带有符号整数类型的操作数的类型可以表示具有无符号整数类型的操作数类型的所有值,则具有无符号整数类型的操作数应转换为带有符号整数的操作数的类型类型。
  •   
  • 否则,两个操作数都应转换为无符号整数类型,对应于带有符号整数类型的操作数类型。
  •   

答案 1 :(得分:4)

在比较(i <= u)期间,i升级为无符号整数,在此过程中-1转换为UINT_MAX。

将负数转换为unsigned int会将(UINT_MAX + 1)添加到该数字,因此-1变为UINT_MAX,-2变为UINT_MAX - 1等。

如果你考虑一下,必须将一个转换为另一个,以便比较甚至工作,并且通常编译器将签名值转换为unsigned。在这种情况下,当然,将无符号值转换为有符号值更有意义,但编译器不能仅根据您的意图决定遵循不同的规范。你应该在这里显式地将unsigned int强制转换为signed(或者只是将其作为一直签名)。

答案 2 :(得分:1)

因为-1被转换为unsigned int,所以for循环代码永远不会被执行。

尝试使用-Wall -Wextra进行编译,这样你就可以得到相应的警告(如果到目前为止没有得到它们,并用g ++编译)

http://en.wikipedia.org/wiki/Two's_complement

答案 3 :(得分:1)

这是因为i在比较之前被提升为无符号值。这会将其设置为UINT_MAX的值,该值在32位机器上等于4294967295。所以你的循环基本上与:

相同
// will never run
for (i = 4294967295; i <= u; i++) {
    count++;
}

答案 4 :(得分:0)

在整数以4个字节存储的系统中,我认为-1的值等于2147483649(1000 0000 0000 0000 0000 0000 0000 0001)的值 - 它是1,MSB设置为1表示它是负