Компилятор: что, если условие всегда верно/false

Я думаю об условностях и компиляторах. Я программирую приложение для Arduino, поэтому мне нужно, чтобы приложение было как можно быстрее.

В моем коде у меня есть это:

#define DEBUG false    

...

if (DEBUG)
{
  String pinName;
  pinName = "Pin ";
  pinName += pin;
  pinName += " initialized";
  Serial.println(pinName);
}

Мне интересно, не компилятор не включает код (код в блоке if) в двоичном файле. Условия всегда ложные, поэтому программа никогда не идет туда.

И с другой стороны. Что делать, если DEBUG верен? Проверяет ли Arduino условие или компилятор включает только тело if в двоичном файле?

Я нашел этот сайт https://gcc.gnu.org/onlinedocs/gcc-3.0.2/cpp_4.html о директиве #if, поэтому я могу переписать код, чтобы иметь эти директивы вместо "нормального", если, Но я хотел бы знать, следует ли мне переписать его или если это будет пустой тратой времени.

Ответ 1

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

Действительно, это полностью эквивалентно "компиляторам", например:

#define DEBUG


#ifdef DEBUG
...
#endif

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

Ответ 2

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

Я бы сказал, что компилятор потребуется для сохранения этого кода, когда вы отключите оптимизацию (например, добавление -O0 в Clang и GCC). Во всех остальных случаях я надеюсь, что компилятор удалит код, так как это очень простая оптимизация с замечательным эффектом размера кода. Например, GCC устраняет это при -O и выше. (См. Руководство )

Хотя есть еще два способа написания вашего кода, который не будет включать этот код:

  • Условия препроцессора
  • constexpr if

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

#ifdef DEBUG
   { // Optional: Adding extra scope to prevent usage of local variables after the endif
   // Code to eliminate
   }
#endif

Однако, если вы используете С++ 17, вы также можете использовать constexpr, если. Это будет менее навязчивым в вашем коде, и хотя код в if-statement должен быть синтаксическим правильным, его не нужно компилировать (так не семантически правильно).

Это можно записать как:

if constexpr (DEBUG)
{
    // Code to eliminate
}

Ответ 3

Мне не нравится отвечать на мой вопрос, потому что я не понял бы это без вашей помощи, ребята.

В любом случае, первый вариант:

#if DEBUG == true
#endif

или

#ifdef DEBUG
#endif

компилятор не получает код в #if/#ifdef (препроцессор удаляет его), поэтому, если в этой части кода есть проблема, никто не узнает об этом, если DEBUG установлен в false или не определен (спасибо @Klaus).

Вторая опция:

#define DEBUG false    

...

if (DEBUG)
{
  ...
}

Любой новый компилятор должен удалить блок "if", если условие является ложным или удаляет оператор "if" и покидает тело, если условие истинно.

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

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

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

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