使用定义(MACRO)的内部C if语句
我想在编写代码C是这样的:使用定义(MACRO)的内部C if语句
if(defined(MACRO)) ... else ...
,但我找不到任何方式Ç要做到这一点,因为定义的(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()
预处理程序操作。
为什么不简单定义ASSERT
取决于该宏?使用C条件语句
#ifdef MACRO
#define ASSERT(NAME, TEST) \
do { \
printf("Assert failed"); \
} while(0)
#else
#define ASSERT(NAME, TEST) {}
#endif
使用固定的值预处理应避免 - 确保编译器应该从优化死代码,但是为什么依靠,当你基本上可以去掉实际的C代码?
编辑:
有相当难看伎俩涉及宏参数字串,你可能能够使用:
#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
本质上,它使用事实上,当预处理器令牌是而不是定义为ma它会扩大到自己。另一方面,当它被定义为时,它将扩展为空字符串或其定义。除非你的一个宏有其自己的名字作为定义,这个黑客应该工作。
免责声明:使用此信息需自担风险!
(...因为我肯定会不使用它!)
编辑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
即使没有优化,海湾合作委员会减少此计划为一个puts()
电话。这个程序产生完全相同的汇编输出:
#include <stdio.h>
int main() {
puts("Error: X");
return 0;
}
因此,你可能不会有任何性能问题,这取决于你的编译器和任何的优化...
不,那是没有好处。我总是想定义ASSERT,但是如果NAME不确定,那么我不想做任何事情。另外,我不想用#ifdef #ifdef – 2011-03-28 19:49:14
@Miklos Maroti将ASSERT的每个用法都括起来:因此NAME的定义不是全局的,而ASSERT是,而且只有在定义了NAME时才需要ASSERT才能工作? – thkala 2011-03-28 19:55:22
我想写这样的代码:ASSERT(UART,var> = 0); ASSERT(SPI,var == 0);因此,如果我定义了UART,那么应该打开所有uart断言,如果我定义了SPI,那么应该打开所有spi断言,并且我不想要预定义的固定数量的子系统,即ASSERT_UART,ASSERT_SPI不是一个好的解决方案。 – 2011-03-28 19:56:40
确定的基础上,以前的帖子我有这个想法,这似乎工作:
#define DEFINEDX(NAME) ((#NAME)[0] == 0) #define DEFINED(NAME) DEFINEDX(NAME)
这将检查名称定义,因此它与0扩展为空字符串在它的第一个字符,或者它在CAS未定义e它不是空字符串。这适用于海湾合作委员会,所以可以写
if(DEFINED(MACRO)) ...
通过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 */
}
的可能重复的[宏取决于宏](http://stackoverflow.com/questions/4927976/macro-dependent-macro) – kennytm 2011-03-28 19:53:29