Постоянное значение в условном выражении

В вопросе стиля кодирования о бесконечных циклах некоторые люди упомянули, что предпочитают стиль for (;;), потому что стиль while (true) дает предупреждающие сообщения на MSVC о постоянном условном выражении.

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

#ifdef CONFIG_FOO
extern int foo_enabled;
#else
#define foo_enabled 0
#endif

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

if (foo_enabled) {
    ...
}

Вместо того, чтобы тестировать CONFIG_FOO каждый раз, когда используется foo_enabled:

#ifdef CONFIG_FOO
if (foo_enabled) {
    ...
}
#endif

Этот шаблон проектирования используется все время в ядре Linux (например, include/linux/cpumask.h определяет несколько макросов в 1 или 0, когда SMP отключен и вызов функции, когда SMP включен).

В чем причина этого предупреждения MSVC? Кроме того, есть ли лучший способ избежать #ifdef hell без необходимости отключать это предупреждение? Или это слишком широкое предупреждение, которое не должно быть включено вообще?

Ответ 1

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

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

Ответ 2

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

const int x = 0;

а затем, вдалеке от объявления x, у вас есть условие вроде:

if (x != 0) ...

Вы можете не заметить, что это постоянное выражение.

Ответ 3

Я считаю, что это поймать такие вещи, как

 if( x=0 )

когда вы имели в виду

 if( x==0 )

Ответ 4

Простым способом избежать предупреждения будет:

#ifdef CONFIG_FOO
extern int foo_enabled;
#else
extern int foo_enabled = 0;
#endif