2013-03-21 2 views
5

У меня трудно понять, почему следующий код не предупреждает:Отсутствие предупреждений на счетчик цикла

unsigned test = 0xffffffff; 

for (unsigned char i = 0; i < test; i++) 
{ 
    // Some code 
} 

Это на Visual Studio 2010, но GCC явно не предупредит либо. Кто-нибудь знает, почему?

+0

Показывать флаги сборки, какие предупреждения вы запрашиваете? – unwind

+1

Потому что предупреждение не является поведением по умолчанию, поэтому нужно сделать случай * для * предупреждения? – Jon

+0

fwiw, там _is_ предупреждение, если вы отметите 'test' как' const'. – mitchnull

ответ

6

С точки зрения языка, об этом нечего предупреждать. i - unsigned int до оценки <. И это совершенно правильно, чтобы увеличить unsigned char таким образом, чтобы он обертывался до нуля.

Тот факт, что этот код вызывает что-то раздражающее, является неудачным. Но неясно, какое правило должен использовать компилятор, чтобы обнаружить такие вещи.

Благодаря @unwind в комментариях ниже: вы можете получить GCC, чтобы предупредить о том, что это сравнение всегда должны оценить истина, используя -Wtype-limits флаг.

Update 2: Видимо вышеуказанная опция не работает в этом случае (я не имею «современную» версию GCC в руки прямо сейчас ...)

+0

Ах .. конечно! Благодарю. –

+1

GCC имеет предупреждение (['-Wtype-limits'] (http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wtype_002dlimits-411)), который предупреждает о всегда-истинных сравнениях, Думаю, это применимо здесь. – unwind

+0

@unwind: Это хороший момент; реальная проблема заключается в том, что сравнение всегда должно оцениваться как истинное. –

1

i повышен до unsigned а затем сравнивали с test. Здесь нет проблем. Что ж. i ++ переполнит char, но это проблема времени выполнения. Я имею в виду, что после 255 это будет 0, и это может быть не то, что автор считает, делая цикл potencialy бесконечным, если нет другой формы его завершения (перерыв, повтор и т. Д.). Это вероятный «логический» " ошибка выполнения.

+0

* «i ++ будет переполнять символ, но это проблема времени выполнения». * - 'i' does * never * overflow, поэтому нет проблемы времени выполнения. –

+0

@Christian Rau Конечно, я имею в виду, что после 255 это будет 0, и это может быть не то, что автор считает, делая цикл potencialy бесконечным, если нет другого для его прекращения (перерыв, перенастройка и т. Д.).) Это допустимая «логическая» ошибка времени выполнения. – qPCR4vir

1

Потому что сравнение unsigned char и unsigned совершенно законно. Проблема возникает только из-за того, что счетчик циклов явно переполнен, но я не уверен, что компиляторы когда-либо будут that smart.

+0

* «Проблема только начинает проявляться из-за переполнения счетчика циклов, но я не уверен, что компиляторы - это умные». * Компилятор тоже не должен быть таким умным, потому что это даже не проблема , поскольку беззнаковые типы никогда не могут переполняться. –

+1

Ну, счетчик циклов просто обертывается после 255, эффективно создавая бесконечный цикл. Вот что я имел в виду ... Я думаю, что правильное слово «нести». –

+0

Да, но это не настоящая проблема, которую нужно диагностировать, поскольку только программист может даже определить, должно ли это происходить или нет. Дело не в том, что компилятор слишком глупый или плохо разбирается, чтобы найти эту «проблему» *. Он просто не должен даже думать об этом. –

1

из проекта стандарта:

4.5 Интегральные акции

prvalue целого типа, кроме BOOL, char16_t, char32_t или wchar_t которого число преобразования ранга (4.13) меньше чем ранг int может быть преобразован в prvalue типа int, если int может представлять все значения типа источника ; в противном случае исходное значение prvalue может быть преобразовано в значение типа unsigned int.

Смежные вопросы