Целые числа без знака в 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).