Какой смысл выдавать предупреждение компилятора для "while (true)" и не выдавать его для "for (;;)"?

Когда я компилирую код С++ с Visual С++ 9 с "уровнем предупреждения 4", выполните следующие действия:

while( true ) {
   //loop body with break on certain condition
}

и следующее:

for( ; true; ) {
   //same loop body
}

оба триггера C4127: conditional expression is constant, но следующее:

for( ; ; ) {
   //same loop body
}

компилируется без предупреждения.

Почему это различие, особенно между вторым и третьим вариантами?

Ответ 1

Причина проста, хотя и глупо.

Важно диагностировать бесконечный цикл, но это может быть не очевидным:

while(i >= 0) { --i; } // infinite if i unsigned

while(SOME_MACRO(i)) // err, depends on the expansion of macros

Это замечательная особенность компилятора для создания предупреждения для тавтологического теста, то есть теста, который оказывается либо всегда истинным, либо всегда ложным, поскольку он не очевиден, когда речь идет о расширении макроса или в пределах зависимый контекст.

Просто кажется, что VС++ слишком сильно продвинулся сюда, и вместо того, чтобы рассматривать тавтологические условия, предупреждает обо всех условиях true или false, которые он может найти, даже если они уже четко указаны в коде.

Ответ 2

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

Ответ 3

Конструкция for ( ;; ) - это канонический способ преднамеренного кодирования "бесконечного" цикла. Я мог представить, что разработчики компилятора не хотели генерировать предупреждение для этого.

Ответ 4

Нет смысла. В конце концов, спецификация langauge говорит ($ 6.5.3/2),

Любое или оба условия и выражение можно опустить. Отсутствующее условие делает подразумеваемое а условие эквивалентно в то время как (истина).

Итак, for ( ; ; ) эквивалентно while(true) даже в соответствии со стандартом. Поэтому я не вижу причин, по которым компилятор должен давать предупреждение в одном случае, но не в другом!

-

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

Я имею в виду, for ( ;; ) скорее будет опечаткой, чем явное упоминание условия в for ( ;true; ). Последний говорит программисту о ясном и ясном намерении. Как Стив говорит в комментарии:

Для значения int y, char x = y является эквивалентно char x = (char) y, но вам может понадобиться предупреждение для неявное сужение конверсии на сначала, но не второй.

Так что явное намерение не должно получать предупреждения, в то время как неявное намерение должно получить!

Ответ 5

Предупреждение компилятора здесь, чтобы помочь поймать возможные ошибки. Использование условия true всегда в цикле while, вероятно, является ошибкой. Например, в следующем коде это, вероятно, ошибка, и я хотел бы, чтобы компилятор предупредил меня об этом:

unsigned int x;
// ...
while (x >= 0) {
    // ...
}

В такой ситуации в оптимизированной сборке компилятор, вероятно, выведет, что условие всегда истинно (поскольку целое число без знака не может быть меньше 0). Таким образом, существует потребность в обнаружении условия true всегда в цикле while. Я думаю, что тот, кто написал обнаружение такой ошибки, не имел особого случая случай while (true), так как существует простой способ сделать бесконечный цикл с помощью for (;;).

Вы можете прочитать здесь, как принято решение добавить предупреждение или нет в Visual Studio (пример примерно C# но я полагаю, что команда имеет такое же правило для предупреждения в C++).