Чтобы условие цикла остановилось в 0 при использовании целых чисел без знака?

У меня есть цикл, который должен пойти от N до 0 (включительно). Мой i переменная имеет тип size_t который обычно не подписан. Я в настоящее время использую следующий код:

for (size_t i = N; i != (size_t) -1; --i) {
    ...
}

Это корректно? Существует ли лучший способ обработать условие?

Спасибо,

Vincent.

11
задан gnuvince 14 August 2010 в 17:54
поделиться

8 ответов

Да, это правильно, и это очень распространенный подход. Я бы не стал его менять.

Арифметика для беззнаковых целочисленных типов гарантированно использует арифметику по модулю 2 ^ N (где N - количество битов значения в типе), а поведение при переполнении четко определено. Результат преобразуется в диапазон от 0 до 2 ^ N - 1 путем добавления или вычитания кратных 2 ^ N (т. Е. По модулю 2 ^ N арифметика).

-1 , преобразованный в целочисленный тип без знака (из которых size_t - один) преобразуется в 2 ^ N - 1 . - также использует арифметику по модулю 2 ^ N для беззнаковых типов, поэтому беззнаковый тип со значением 0 будет уменьшен до 2 ^ N - 1 . Ваше условие завершения цикла правильное.

7
ответ дан 3 December 2019 в 04:12
поделиться
for (i=N; i+1; i--)
1
ответ дан 3 December 2019 в 04:12
поделиться

Поскольку беззнаковое целое число при уменьшении с нуля переходит в максимальное значение, вы можете попробовать следующее, при условии, что N меньше этого максимального значения (кто-нибудь, пожалуйста, поправьте меня, если это UB ):

for ( size_t i = N; i <= N; i-- ) { /* ... */ }
0
ответ дан 3 December 2019 в 04:12
поделиться

Вы можете использовать это:

for (size_t i = n + 1; i-- > 0;)
{
}

Надеюсь, что это поможет.

4
ответ дан 3 December 2019 в 04:12
поделиться

Тот факт, что для имеет удобное место для размещения теста в начале каждой итерации, не означает, что вы должны его использовать. Чтобы обработать N до 0 включительно , тест должен быть в конце, по крайней мере, если вы заботитесь об обработке максимального значения. Не позволяйте удобству втянуть вас в то, чтобы поставить тест в неправильном месте.

for (size_t i = N;; --i) {
    ...
    if (i == 0) break;
}

Цикл do-while также будет работать, но тогда вы дополнительно откажетесь от привязки i к циклу.

5
ответ дан 3 December 2019 в 04:12
поделиться

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

for (size_t j=0, i=N; j<=N; ++j, --i) {
    // code here ignores j and uses i which runs from N to 0
    ...
}
1
ответ дан 3 December 2019 в 04:12
поделиться

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

size_t i = N;
do {
    ...
} while (i --> 0);

(можно просто использовать (i--) в качестве условия цикла, но никогда не следует упускать шанс использовать "оператор" -->).

4
ответ дан 3 December 2019 в 04:12
поделиться
for ( size_t i = N ; i <= N ; i-- ) { .... }

Это сработает, потому что size_t - это целое число без знака. Беззнаковые целые числа - 32 бита. Когда переменная i имеет значение 0, вы хотите, чтобы ваш цикл выполнял условие. Если вы выполните i--, компьютер выполнит

 00000000000000000000000000000000
-00000000000000000000000000000001

, что приведет к явному переполнению, давая значение 111111111 ... 1. Для целого числа с дополнением до двух со знаком это значение явно отрицательное. Однако тип i - это целое число без знака, поэтому компьютер интерпретирует 111111 ... 1 как очень большое положительное значение.

Итак, у вас есть несколько вариантов:

1) Сделайте то, что указано выше, и завершите цикл при переполнении.

2) Запустите цикл от i = 0 до i <= N, но используйте (N-i) вместо i везде в вашем цикле. Например, myArray [i] превратится в myArray [N-i] (отличается на единицу в зависимости от того, что на самом деле представляет значение N).

3) Сделайте так, чтобы условие цикла for использовало приоритет унарного оператора -. Как написал другой пользователь:

for ( size_t i = N + 1 ; i-- > 0 ; ) { ... }

Это установит i в N + 1, проверьте, выполняется ли условие N + 1> 0. Есть, но у i-- есть побочный эффект, поэтому значение i уменьшается до i = N. Продолжайте, пока не дойдете до i = 1. Условие будет тестовым, 1> 0 истинно, возникает побочный эффект. , тогда i = 0, и он выполняется.

3
ответ дан 3 December 2019 в 04:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: