为什么在使用C++的表达式中使用无符号整数时会出错?

neu*_*rte 2 c++ unsigned expression

给出以下(伪C++)代码:

float x=100, a=0.1;
unsigned int height = 63, width = 63;
unsigned int hw=31;
for (int row=0; row < height; ++row)
{
    for (int col=0; col < width; ++col)
    {
        float foo = x + col - hw + a * (col - hw);
        cout << foo << " ";
    }
    cout << endl;
}
Run Code Online (Sandbox Code Playgroud)

在(col - hw)为负的地方,foo的值被拧紧了一半的数组.我想因为col是int而且是第一个,表达式的这一部分转换为int并变为负数.不幸的是,显然它没有,我得到一个无符号值的溢出,我不知道为什么.

我该如何解决这个问题?使用强制转换表达整个或部分表达式?什么类型的演员表(C风格或static_cast <...>)?使用演员阵容是否有任何开销(我需要这个快速工作!)?

编辑:我将所有未签名的int更改为常规int,但我仍然想知道为什么在这种情况下我有溢出.

AnT*_*AnT 7

无符号整数实现无符号算术.无符号算术是模数算术.所有值都以2 ^ N为模调整,其中N是无符号类型的值表示中的位数.

简单来说,无符号算术总是产生非负值.每次表达式应该导致负值时,该值实际上"包围"2 ^ N并变为正值.

在[sub-]表达式中混合有符号和无符号整数时,无符号算术"获胜",即计算在无符号域中执行.例如,当你这样做时col - hw,它被解释为(unsigned) col - hw.这意味着,col == 0hs == 31您将无法获得-31作为结果.相反,你会得到UINT_MAX - 31 + 1,这通常是一个巨大的积极价值.

话虽如此,我必须指出,在我看来,使用无符号类型来表示固有的非负值总是一个好主意.实际上,在实践中,C/C++中的大多数(或至少一半)整数变量应该具有无符号类型.您在示例中尝试使用无符号类型是合理的(如果正确理解了意图).此外,我会使用unsignedcolrow为好.但是,您必须记住无符号算术的工作方式(如上所述)并相应地编写表达式.大多数情况下,可以重写表达式,使其不超过无符号范围的界限,即大多数情况下不需要显式地将任何内容转换为有符号的类型.否则,如果您确实需要最终使用负值,则对签名类型进行良好放置的转换应该可以解决问题.

  • 我必须不同意"使用无符号类型总是一个好主意".我的银行帐户*应该*始终是肯定的.但是使用无符号数量意味着如果出现问题,我最终会得到巨大的积极平衡.好.也许银行*应该*在非信用账户上使用未签名的数量:P (2认同)
  • 重要的是实体是否可以在语义上消极.我的银行中的余额可以为负值,但电子表格中的行数不能.只有在符合您的类型语义的情况下才使用unsigned,并且只有在您愿意付出额外努力以避免欠载时才使用. (2认同)