2016-08-19 2 views
12

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

В моем коде я это:

#define DEBUG false  

... 

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

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

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

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

+3

Умный компилятор выполнит оптимизацию и не будет включать код в двоичном формате, если 'DEBUG' является' false'. –

+7

'if (CONSTANT) {...}' очень просто для компилятора для оптимизации. Я ожидал бы, что любой достойный компилятор, по крайней мере, за последние 25 лет, сможет удалить условную ветвь. – Phylogenesis

+4

Я бы использовал '# if' /' # endif', даже если это не влияет на двоичный файл. Таким образом, понятно, что такое DEBUG. – LogicStuff

ответ

8

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

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

#define DEBUG 


#ifdef DEBUG 
... 
#endif 

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

1

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

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

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

  • препроцессор условных
  • constexpr если

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

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

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

Это можно записать в виде:

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

это 'if constexpr'? – RiaD

+0

Нет, это 'constexpr if'. Я добавил ссылку на предложение в своем ответе. – JVApen

+0

Я считаю, что это устарело http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0292r1.html https://herbsutter.com/2016/06/30/trip-report- summer-iso-c-standards-meeting-oulu/ – RiaD

0

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

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

#if DEBUG == true 
#endif 

или

#ifdef DEBUG 
#endif 

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

Второй вариант:

#define DEBUG false  

... 

if (DEBUG) 
{ 
    ... 
} 

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

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

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

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

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

+0

'#if DEBUG == true' можно заменить на' #if DEBUG'. Другим вариантом является '#ifdef DEBUG'. Для некоторых определений, таких как параметры библиотеки, вы можете использовать стиль '# if', но специально для' DEBUG' лучше использовать синтаксис '# ifdef'. – i486

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