2015-01-23 4 views
3

фонкомпилятор предупреждает об отсутствии символ препроцессора

У меня есть C проект, который имеет заголовочный файл настроек, например:

// config.h 
#define FEATURE_1_AVAILABLE  1 
#define FEATURE_2_AVAILABLE  0 
#define FEATURE_3_AVAILABLE  1 

модули используют эти флаги для включения/исключения объектов из сборки :

#include "config.h" 
void foo(void) { 
    ... 
    #if FEATURE_1_AVAILABLE 
    useFeature1(); 
    #endif 
    ... 

Существуют разные версии config.h для разных сборок.

Проблема

#include "config.h" получил случайно удалены, поэтому функция не активна, даже когда он был включен в конфигурации.

К сожалению, #if FEATURE_1_AVAILABLE молча оценивает 0, когда не определено. Поэтому мне нужна ошибка, если она не определена.

Вариант 1

Я мог бы добавить дополнительный 'если определено' тест на каждом состоянии.

#ifndef FEATURE_1_AVAILABLE 
    #error No feature 1 
#elif FEATURE_1_AVAILABLE 
    useFeature1(); 
#endif 

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

Вариант 2

Добавить одного теста в начале модуля:

#ifndef FEATURE_1_AVAILABLE 
    #error No feature 1 
#endif 

Но это может быть потерян/забыт по тем же причинам, что #include "config.h" было.

Вариант 3

Определить флаги в виде макросов:

#define FEATURE_1_AVAILABLE()  1 

и использовать как:

#if FEATURE_1_AVAILABLE() 

Unfortunaltely это также потерпит неудачу тихо, если вы забыли скобку:

#if FEATURE_1_AVAILABLE 

Опция X

Есть ли лучший вариант? Что-то, что даст сообщение об ошибке во время компиляции, если символ не определен или неправильно написан. И, надеюсь, не превращает код в незаметный препроцессорный беспорядок.

Другие вещи

  • время выполнения проверки не представляется возможным. Отключенные функции не должны находиться в двоичном формате.
  • Особенности должны быть определены в файле. Определение их как глобальных параметров компилятора имеет другие проблемы.
  • Это для встроенной системы. Некоторые из этих функций требуют аппаратного обеспечения для работы, и тестирование очень трудоемко. Таким образом, предпочтение отдается ошибкам во время компиляции.
+0

Найти лицо, ответственное за удаление включают, и боп этот человек на голове. Если вам действительно нужен такой файл заголовка, который входит во все исходные файлы, все разработчики должны это знать. Кроме того, такие вещи должны были автоматически определяться автоматическими модульными тестами (у вас есть * автоматические модульные тесты?) И были бы исправлены до того, как программа когда-либо достигнет клиента. –

+1

@JoachimPileborg Но я не хочу ударить себя :) Это было удалено случайно. О модульных тестах: Как я уже писал, тестирование некоторых из них без аппаратного обеспечения невозможно. Поэтому такие ошибки дешевле исправить, когда они обнаружены во время компиляции. – user694733

+0

@ JimBalter При быстром взгляде это может быть обман. Я буду смотреть дальше и закрыть это, если это так. – user694733

ответ

3

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

С gcc, например, есть -Wundef вариант (не входит в -Wall):

#if FEATURE_1_AVAILABLE 
useFeature1(); 
#endif 

это дает предупреждение (добавить -Werror, чтобы сделать его ошибку):

tst.c:6:9: warning: "FEATURE_1_AVAILABLE" is not defined [-Wundef] 
    #if FEATURE_1_AVAILABLE 

Эта опция также доступен с другими компиляторами, например. г. clang и icc.

+2

Обратите внимание, что это предупреждение может дать много ложных срабатываний, особенно в системах, которые используют макросы препроцессора для проверки совместимости платформ. –

+0

@JoachimPileborg это вариант, который я обычно использую в своих программах (но только если я получаю предупреждение от других сторонних программ/libs) – ouah

+0

Это хорошее предложение, но в моем случае было бы много ложных срабатываний с 3-го партийных библиотек. – user694733

0

Я знаю, что это being frowned upon, но для небольших проектов C нет ничего плохого в том, один проект шириной включаемый файл (скажем myproject.h) со всеми вашими #include .. директив (как #include "config.h"), а затем только #include "myproject.h в верхней части каждого исходного файла.

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

В качестве альтернативы, вы могли бы поставить один существенный #include (скажем #include assert.h) в вашем config.h (и только там), опять же раздражать компилятор/линкер, когда вы забыли включить его

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

  • Нет связанных вопросов^_^