В целом, основная проблема, как представляется, тот факт, что 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
и т.д. символы как неопределенные.
Вы уверены, что 'main.c' не включает * что-то, что включает' config.h'? –
@EugeneSh. 100% Конечно. – s7amuser
Вы можете проверить, является ли 'CONFIG_COLOR' предопределенным макросом, используя' #if! Defined (CONFIG_COLOR) ',' #error CONFIG_COLOR не определен! ',' # Endif'. –