Использование определенного (MACRO) внутри оператора C if - PullRequest
10 голосов
/ 28 марта 2011

Я хотел бы написать код в C примерно так:

if(defined(MACRO))
  ...
else
  ...

но я не смог найти никакого способа сделать это в C , так как определенный оператор препроцессора (MACRO) работает только внутри # if. Есть ли способ сделать это?

Что мне действительно нравится делать, так это писать:

ASSERT(UART, var >= 0);

, где

#define ASSERT(NAME, TEST) \
  do { \
    if (defined(NAME) && !(TEST)) \
      printf("Assert failed"); \
  } while(0)

, таким образом, я мог бы включить проверку ASSERT, когда макрос определен и, если он не определен, утверждения не должны проверяться. Если вы попытаетесь это сделать, то получите:

implicit declaration of function `defined'

, что вполне понятно, поскольку компилятор GCC не находит оператора препроцессора defined().

Ответы [ 3 ]

11 голосов
/ 12 апреля 2012

Макрос с помощью comex расширяется до 1, если аргумент определен как 1. В противном случае он расширяется до 0:

#define is_set(macro) is_set_(macro)
#define macrotest_1 ,
#define is_set_(value) is_set__(macrotest_##value)
#define is_set__(comma) is_set___(comma 1, 0)
#define is_set___(_, v, ...) v

Вы можете использовать его следующим образом:

if (is_set(MACRO)) {
   /* Do something when MACRO is set */
}
5 голосов
/ 29 марта 2011

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

#define DEFINEDX(NAME) ((#NAME)[0] == 0)
#define DEFINED(NAME) DEFINEDX(NAME)

Это проверит, определено ли NAME, и, следовательно, расширится до пустой строки с 0 в первом символе.или он не определен, в этом случае это не пустая строка.Это работает с GCC, так что можно написать

if( DEFINED(MACRO) )
  ...
2 голосов
/ 28 марта 2011

Почему бы вам просто не определить ASSERT по-разному в зависимости от этого макроса?

#ifdef MACRO
#define ASSERT(NAME, TEST) \
    do { \
        printf("Assert failed"); \
    } while(0)
#else
#define ASSERT(NAME, TEST) {}
#endif

Следует избегать использования фиксированных значений препроцессора в условных выражениях на C - конечно, компилятор должен оптимизировать мертвый код, но зачем полагаться на это, когда вы можете по существу удалить действительный код на C?

EDIT:

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

#include <string.h>
#include <stdio.h>

#define X

#define ERROR_(NAME, TEXT) \
        if (strcmp("", #NAME) == 0) \
                printf("%s\n", TEXT)
#define ERROR(n, t) ERROR_(n, t)

int main() {
    ERROR(X, "Error: X");
    ERROR(Y, "Error: Y");

    return 0;
}

Это выводит:

$ ./test
Error: X

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

Отказ от ответственности: используйте это на свой страх и риск!

(... потому что я наверняка не воспользуюсь им!)

РЕДАКТИРОВАТЬ 2:

Вывод сборки gcc -O0 -S для указанной выше программы:

        .file   "test.c"
        .section        .rodata
.LC0:
        .string "Error: X"
        .text
.globl main
        .type   main, @function
main:
.LFB0:
        .cfi_startproc
        pushq   %rbp
        .cfi_def_cfa_offset 16
        movq    %rsp, %rbp
        .cfi_offset 6, -16
        .cfi_def_cfa_register 6
        movl    $.LC0, %edi
        call    puts
        movl    $0, %eax
        leave
        ret
        .cfi_endproc
.LFE0:
        .size   main, .-main
        .ident  "GCC: (GNU) 4.4.3"
        .section        .note.GNU-stack,"",@progbits

Даже без оптимизации GCC сокращает эту программу до одного puts() вызова. Эта программа выдает точно такой же вывод сборки:

#include <stdio.h>

int main() {
    puts("Error: X");

    return 0;
}

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

...