Целые числа без знака в C++ для циклов

Я провел некоторое исследование Stackoverflow об обратном для циклов в C++, которые используют целое число без знака вместо подписанного. Но я до сих пор не понимаю, почему возникает проблема (см. Unsigned int обратная итерация с циклами for). Почему следующий код приведет к ошибке сегментации?

#include <vector>
#include <iostream>
using namespace std;

int main(void)
{
    vector<double> x(10);

    for (unsigned int i = 9; i >= 0; i--)
    {
        cout << "i= " << i << endl;
        x[i] = 1.0;
    }

    cout << "x0= " << x[0] << endl;

    return 0;
}

Я понимаю, что проблема в том, когда индекс i будет равен нулю, потому что есть что-то вроде переполнения. Но я думаю, что целое число без знака разрешено принимать нулевое значение, не так ли? Теперь, если я заменю его целым числом со знаком, нет абсолютно никаких проблем.

кто-нибудь может объяснить мне механизм этого обратного цикла с целым числом без знака?

большое спасибо!

4 ответов


проблема здесь в том, что целое число без знака никогда не отрицательно.

таким образом, цикл испытаний:

i >= 0

всегда будет правдой. Таким образом вы получаете бесконечный цикл.

когда он падает ниже нуля, он оборачивается к самому большому значению unsigned значение.
таким образом, вы также будете иметь доступ x[i] за пределами.

это не проблема для целых чисел со знаком, потому что он просто будет отрицательным и, таким образом, потерпит неудачу i >= 0.

таким образом, если вы хотите использовать целые числа без знака, вы можете попробовать одну из следующих возможностей:

for (unsigned int i = 9; i-- != 0; )

и

for (unsigned int i = 9; i != -1; i--)

эти два были предложены GManNickG и AndreyT из комментариев.


и вот мои оригинальные 3 версии:

for (unsigned int i = 9; i != (unsigned)0 - 1; i--)

или

for (unsigned int i = 9; i != ~(unsigned)0; i--)

или

for (unsigned int i = 9; i != UINT_MAX; i--)

проблема в том, что ваш цикл позволяет i быть равным нулю и ожидает выхода из цикла, только если i меньше 0. Поскольку i не имеет знака, он никогда не может быть меньше 0. Он переворачивается на 2^32-1. Это больше, чем размер вашего вектора, и поэтому приводит к segfault.


независимо от значения unsigned int i это всегда правда, что i >= 0 Так что ваши for цикл никогда не заканчивается.

иными словами, если в какой-то момент i равно 0, и вы уменьшаете его, он по-прежнему остается неотрицательным, потому что он содержит тогда огромное число, вероятно, 4294967295 (то есть 232-1).


проблема:

for (unsigned int i = 9; i >= 0; i--) 

вы начинаете со значения 9 для unsigned int, а ваше определение выхода-i >= 0, и это всегда будет верно. (unsigned int никогда не будет отрицательным!!!). Из-за этого ваш цикл начнется заново (бесконечный цикл, потому что i=0, а затем -1 идет max uint).