C++ 为什么在for循环中相同的条件下得到不同的结果?

C++ 为什么在for循环中相同的条件下得到不同的结果?,c++,for-loop,signed,C++,For Loop,Signed,当我试图使用for循环来解决问题时,我被卡住了 以下是我的简化代码: int main(int argc, const char * argv[]) { std::vector<int> a; a.push_back(2333); int n = 10, m = 10; for(int i=0; i< -1; i++) m--; std::cout<<m<<endl; for(int j=0

当我试图使用
for
循环来解决问题时,我被卡住了

以下是我的简化代码:

int main(int argc, const char * argv[])
{
    std::vector<int> a;
    a.push_back(2333);
    int n = 10, m = 10;
    for(int i=0; i< -1; i++)
        m--;
    std::cout<<m<<endl;
    for(int j=0; j<a.size()-2; j++)
        n--;
    std::cout<<n<<endl;
    return 0;
}
int main(int argc,const char*argv[]
{
std::载体a;
a、 推回(2333);
int n=10,m=10;
对于(int i=0;i<-1;i++)
m--;

std::couta.size()返回的值
是否为类型
size\u t
,它是一个无符号整数,因为没有任何理由使大小为负数。如果对无符号数字执行1-2操作,它将滚动并成为一个接近无符号整数最大值的值,循环将需要相当长的时间才能运行,甚至可能不会停止,因为有符号整数可以'不能大于无符号值的上半部分。这取决于比较有符号值和无符号值的规则,我当时不太清楚


使用调试器并确保类型正确(编译器应在此处提及有符号/无符号不匹配)有助于确定这些情况。

size()返回的值
std::size\u t
,它是一种无符号整数类型。这意味着它只能表示非负数,如果您执行的操作导致负数,它将像模运算一样,环绕到可能的最大值

这里,
2-1
是-1,它在32位系统上换行为
2^32-1
。当您尝试从10中减去
2^32-1
时,会导致有符号整数下溢,因为32位整数的最小值是
-2^31
。有符号整数上溢/下溢是,所以任何事情都可能发生

在这种情况下,看起来底流就像一个带符号的整数一样缠绕到最大值。因此结果将是
10-(2^32-1)+2^32
,即11。我们添加
2^32
来模拟底流环绕。换句话说,在循环的
2^31+10
第次迭代之后,
n
是32位整数中可能的最小值。下一次迭代导致环绕,因此
n
现在是
2^31-1
。然后,剩余的<代码>2^31-12次迭代次数减少到11次


同样,有符号整数溢出/下溢是未定义的行为,因此,如果因此而发生奇怪的事情,尤其是现代编译器优化,请不要感到惊讶。例如,您的整个程序都可以“优化”如果
a.size()
是有符号类型,则绝对不执行任何操作,因为它将始终调用UB。您甚至不能保证看到
std::cout
a.size()-2的输出将导致-1。因为
a.size()
是无符号类型,
a.size()-2
会产生一个非常大的正数。例如。那么你能告诉我为什么它会产生这么大的正数,为什么n仅仅等于11吗?@rsahi会让别人来解释。恐怕我脑子里没有所有的部分。当你遇到这样一个令人惊讶的结果时,第一步就是e检查你的假设。例如,添加
std::cout