C ++:由vector.size()除法给出了奇怪的结果

时间:2013-01-10 10:26:21

标签: c++ vector std division integer-division

  

可能重复:
  int divided by unsigned int causing rollover

您好我正在做以下事情:

struct coord{
    int col;

};


int main(int argc, char* argv[]) {

    coord c;
    c.col = 0; 

    std::vector<coord> v;

    for(int i = 0; i < 5; i++){
        v.push_back(coord());
    }

    c.col += -13;


    cout << " c.col is " << c.col << endl;
    cout << " v size is " << v.size() << endl;

    c.col /= v.size();


    cout << c.col << endl;

}

我得到以下输出:

 c.col is -13
 v size is 5
858993456

但是,如果我将分割线更改为c.col /= ((int)v.size());,我会得到预期的输出:

 c.col is -13
 v size is 5
-2

为什么会这样?

4 个答案:

答案 0 :(得分:5)

这是v.size() unsigned的结果。

请参阅int divided by unsigned int causing rollover

答案 1 :(得分:4)

问题是vector< ... >::size()返回size_ttypedef整数类型的unigned。显然,当您使用无符号整数除以有符号整数时会出现问题。

答案 2 :(得分:2)

std :: vector :: size返回size_t,这是一个无符号整数类型,通常是 unsigned int 。当您使用 int unsigned int 执行算术运算时, int 操作数将转换为 unsigned int 执行操作。在这种情况下,-13转换为 unsigned int ,这是一些接近4294967295的数字(以十六进制表示的FFFFFFFF)。然后除以5。

答案 3 :(得分:1)

如上所述,原因是通过首先将有符号值转换为无符号值来执行有符号/无符号除法。

因此,您需要通过手动将无符号值转换为有符号类型来防止这种情况。

v.size()存在int可能过大的风险。但由于红利 适合int,因此当除数大于该值时,除法的结果相当无聊。所以假设2的补码而没有填充位:

if (v.size() <= INT_MAX) {
    c.col /= int(v.size());
} else if (c.col == INT_MIN && v.size() - 1 == INT_MAX) {
    c.col = -1;
} else {
    c.col = (-1 / 2);
}

在C ++ 03中,它的实现定义了负值除以较大的正值是0还是-1,因此有趣(-1 / 2)。在C ++ 11中,您可以使用0。

要涵盖除2的补码之外的其他表示,您需要以不同方式处理特殊情况。