2017-02-06 3 views
1

заголовка файла config.h содержит следующие операторы:Force ARM компилятор выдавать неопределенном Macro Error

#define RED 0 
#define BLUE 1 
#define GREEN 2 
#define CONFIG_COLOR RED 

Исходный файл main.c делает не включать config.h, но содержит следующее:

#if CONFIG_COLOR == RED 
/* Red code */ 
#elif CONFIG_COLOR == BLUE 
/* Blue code */ 
#elif CONFIG_COLOR == GREEN 
/* Green code */ 
#endif 

тонарма компилятор ARMCC (или, скорее, предварительный процессор C) не выдает никаких предупреждений или ошибок при компиляции main.c, хотя CONFIG_COLOR не определен.

Есть ли способ заставить компилятор выпустить ошибку в вышеуказанном случае?

В качестве альтернативы, есть ли способ заставить Keil ARM uVision IDE всегда включать config.h для каждого исходного файла?

Я знаю, что в GCC есть флаги для обоих.

+0

Вы уверены, что 'main.c' не включает * что-то, что включает' config.h'? –

+0

@EugeneSh. 100% Конечно. – s7amuser

+0

Вы можете проверить, является ли 'CONFIG_COLOR' предопределенным макросом, используя' #if! Defined (CONFIG_COLOR) ',' #error CONFIG_COLOR не определен! ',' # Endif'. –

ответ

0

Всякий раз, когда символ не определен в директиве #if/#elif, он просто заменяется на 0. Таким образом, если CONFIG_COLOR никоим образом не определяются, код такого же, как:

#if 0 == RED 
/* Red code */ 
#elif 0 == BLUE 
/* Blue code */ 
#elif 0 == GREEN 
/* Green code */ 
#endif 

Это может привести к безобразным ошибкам, если, например, RED определяется как 0, и, таким образом, первое условие становится истинным. Можно условно остановить компиляцию с ошибкой, если CONFIG_COLOR не определен через #error:

#ifndef CONFIG_COLOR 
    #error CONFIG_COLOR is not defined! 
#endif 

Вы также можете дать GCC/Clang в -Wl,-Wundef возможность бросить предупреждение всякий раз, когда это произойдет. Это может быть сделано в результате полной продувки с помощью опции -Wl,-Werror.

+0

Как я писал в комментариях к исходному вопросу, я знаю, что это возможно, но таким образом программист * должен * не забыть поставить директиву #error. Я предпочитаю компилятор (который, очевидно, имеет необходимые знания), чтобы проинформировать программиста в этом случае. В GCC это возможно. – s7amuser

+0

* Как это возможно в GCC? –

+0

@ s7amuser: Смотрите мое редактирование. GCC имеет возможность сделать именно это. – 3442

1

В целом, основная проблема, как представляется, тот факт, что armcc C препроцессора/компилятор не имеет возможности предупредить, если неопределенные макросы препроцессора используются в #if директивах препроцессора, и разработчики низовий нуждаются намеков получить их код работает правильно.


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

#if defined(CONFIG_COLOR_IS_RED) 
/* Red case */ 
#elif defined(CONFIG_COLOR_IS_GREEN) 
/* Green case */ 
#elif defined(CONFIG_COLOR_IS_BLUE) 
/* Blue case */ 
#else 
#error config.h is not included! 
#endif 

Разработчики нижестоящих программ должны включать в себя весь блок, конечно. (Который, как представляется, является проблемой для OP, то downstreamers может быть, скорее всего, забыть или неправильно редактировать блок.)


Другим вариантом было бы сделать выбор на уровне экспрессии (в отличие от блока уровня); то естьиспользуя макро

CONFIG_COLOR(red-expression, green-expression, blue-expression) 

который определен в config.h, как, например,

#if defined(CONFIG_COLOR_IS_RED) 
#define CONFIG_COLOR(red, green, blue) (red) 
#elif defined(CONFIG_COLOR_IS_GREEN) 
#define CONFIG_COLOR(red, green, blue) (green) 
#elif defined(CONFIG_COLOR_IS_BLUE) 
#define CONFIG_COLOR(red, green, blue) (blue) 
#else 
#error Color not configured! 
#endif 

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

В этом случае код пользователя довольно просто, например

my_color_attribute = CONFIG_COLOR(my_red, my_green, my_blue); 

или константы или выражения вместо my_red, my_green и my_blue. Как вы видите, макрос выбирает одно значение из трех, в зависимости от выбранного «цвета».


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

IF_RED 
    /* Red case */ 
ENDIF 
IF_GREEN 
    /* Green case */ 
ENDIF 
IF_BLUE 
    /* Blue case */ 
ENDIF 

где макросы определены в config.h как, например,

#if defined(COLOR_IS_RED) 
#define IF_RED if (1) { 
#define IF_GREEN if (0) { 
#define IF_BLUE if (0) { 
#elif defined(COLOR_IS_GREEN) 
#define IF_RED if (0) { 
#define IF_GREEN if (1) { 
#define IF_BLUE if (0) { 
#elif defined(COLOR_IS_BLUE) 
#define IF_RED if (0) { 
#define IF_GREEN if (0) { 
#define IF_BLUE if (1) { 
#else 
#error Color not selected! 
#endif 
#define END_IF } 

, который генерирует недействительный код (код, который никогда не будет достигнут) для не выбранных кодов; компилятор должен иметь возможность оптимизировать ветви, хотя я не уверен, нужны ли какие-либо опции для armcc.

Если заголовочный файл config.h не включен, тогда компилятор будет дросселировать на IF_RED и т.д. символы как неопределенные.

+0

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

+0

@KemyLand: Что вы подразумеваете под * «кажущимися случайными синтаксическими ошибками» *? Случаи, когда 'config.h' не включаются, дают очень отчетливые сообщения об ошибках компилятора и сообщения о времени соединения. Если 'config.h' уже включен, можно ожидать, что пользователь прочитает документацию, где явно указывается, какие сообщения об ошибках можно ожидать от неправильного использования. Честно говоря, я ничего не вижу * «кажущийся случайным» *. И если разработчики нисходящего потока действительно ненадежны, я бы сказал, что это даже не «хаки» *, а просто пропущенные ключи. –

+0

@NominalAnimal Благодарим вас за ответ. Я до сих пор не уверен, что это лучшее решение. Возможно, в конце концов я поставлю #error, если 'CONFIG_COLOR' не определен ... – s7amuser

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