Ошибка сравнения бесконечного цикла без знака в C ++

Заметил ошибку в одной из программ, над которой я работал, извлек код, и в основном это так.
Он выполняет сравнение без знака со знаком int и приводит к бесконечному циклу:

#include <iostream>  

int main()
{
    unsigned int i = 0;
    while (i < 1000000)
    {
        printf("%o\n", i);
        ++i;
    }
    return 0;
}

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

#include <iostream>

int main()
{
    unsigned int i = 0;
    while (i < 1000000u)
    {
        printf("%o\n", i);
        ++i;
    }
    return 0;
}

Что, как я думал, исправит сравнение подписанного / неподписанного, но это не так, он все еще попадает в бесконечный цикл. Поэтому я также попытался преобразовать его в unsigned int и без кубиков, по-прежнему бесконечные циклы.

Использование Visual Studio 2015, полная оптимизация, релизный компилятор.


person Brian Deragon    schedule 21.08.2016    source источник
comment
Вы уверены, что это бесконечный цикл? Мне это кажется очень длинным циклом, тем более что печать занимает много времени. Измените на i += 1000, чтобы проверить, работает ли условие выхода.   -  person Sergey Kalinichenko    schedule 22.08.2016
comment
Это не проблема сравнения со знаком / без знака. Значение 1000000 находится в обоих диапазонах, и вы пытались решить проблему, предполагая, что это причина ее, но это не сработало.   -  person AhmadWabbi    schedule 22.08.2016
comment
Почему вы #include <iostream>, а потом используете printf?   -  person dxiv    schedule 22.08.2016
comment
Просто для справки: первая программа работает должным образом (вывод чисел) с gcc 5.3.1 на 64-битном Linux. Вы уверены, что проблема не только в медленном printf?   -  person MTilsted    schedule 22.08.2016
comment
они использовали cout в исходном коде, который был намного медленнее .... в основном в целях тестирования, printf для тестирования быстрее   -  person Brian Deragon    schedule 22.08.2016
comment
@MTilsted он работает для меня с gcc, используя mingw, он не работает с компилятором VC ++   -  person Brian Deragon    schedule 22.08.2016
comment
Я не могу поменять компилятор для корпоративного проекта, который намного больше этого   -  person Brian Deragon    schedule 22.08.2016


Ответы (2)


Хотя я не могу воспроизвести бесконечный цикл на Win7 или Ubuntu (оба 64-разрядных), я считаю, что проблема заключается в вашей функции printf () с представлением беззнакового восьмеричного числа, что заставляет вас думать, что она входит в бесконечный цикл. Изменение параметра %o на %u может прояснить проблему.

person Community    schedule 21.08.2016
comment
Ха, очевидно, это правда, std :: cout ‹< std :: oct ‹< n ​​‹< '\ n' также изменяет базовое целое число на восьмеричное, что они и использовали изначально. - person Brian Deragon; 22.08.2016

Это связано с переполнением типа int. См. Тип ограничений. Для такого сравнения большого числа вы должны использовать long вместо int

person Steephen    schedule 21.08.2016
comment
Возможно, но в наши дни int на большинстве платформ не менее 32 бита. - person Blorgbeard; 22.08.2016
comment
Вряд ли будет так. OP упомянул VS 2015, где тип int по умолчанию 32-битный, что намного шире, чем требуется 1000000. - person dxiv; 22.08.2016
comment
и его 64-разрядная версия, скомпилированная на VC ++, печатает числа, просто не останавливается, пока не достигнет предела; а затем из-за неподписанных правил он все еще не останавливается, он просто начинается заново - person Brian Deragon; 22.08.2016
comment
@BrianDeragon unsigned int по-прежнему 32-битный в VC ++ 2015, даже для 64-битной компиляции. - person dxiv; 22.08.2016
comment
long часто бывает того же размера, что и int. Для больших чисел вы, вероятно, не должны ничего предполагать и вместо этого просто используйте тип, гарантированно имеющий определенный минимальный размер; они существуют не просто так. Однако эта проблема с размером не является проблемой для начала, учитывая 32-битный целочисленный тип без знака, который вы можете как бы считать нормой для Visual Studio 2015. - person Andon M. Coleman; 22.08.2016