Mik*_*oti 11 gcc c-preprocessor
我想用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()
预处理器运算符.
vit*_*aut 11
如果参数定义为1,则comex的宏将扩展为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
Run Code Online (Sandbox Code Playgroud)
您可以按如下方式使用它:
if (is_set(MACRO)) {
/* Do something when MACRO is set */
}
Run Code Online (Sandbox Code Playgroud)
好的,基于上一篇文章,我得到了这个想法,这似乎有效:
#define DEFINEDX(NAME) ((#NAME)[0] == 0) #define DEFINED(NAME) DEFINEDX(NAME)
这将检查NAME是否已定义,因此它将扩展为空字符串,其第一个字符为0,或者未定义,在这种情况下,它不是空字符串.这适用于GCC,所以可以写
if( DEFINED(MACRO) ) ...
为什么不简单地ASSERT
根据该宏进行不同的定义?
#ifdef MACRO
#define ASSERT(NAME, TEST) \
do { \
printf("Assert failed"); \
} while(0)
#else
#define ASSERT(NAME, TEST) {}
#endif
Run Code Online (Sandbox Code Playgroud)
应避免在 C 条件中使用固定的预处理器值 - 确保编译器应该优化死代码,但当您基本上可以删除实际的 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;
}
Run Code Online (Sandbox Code Playgroud)
这输出:
$ ./test
Error: X
Run Code Online (Sandbox Code Playgroud)
本质上,它利用了这样一个事实:当预处理器标记未定义为宏时,它会扩展为自身。另一方面,当它被定义时,它会扩展为空字符串或其定义。除非您的宏之一有自己的名称作为定义,否则此技巧应该有效。
免责声明:使用此工具需要您自担风险!
(...因为我肯定不会使用它!)
编辑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
Run Code Online (Sandbox Code Playgroud)
即使没有进行优化,GCC 也会将该程序简化为一次puts()
调用。该程序产生完全相同的汇编输出:
#include <stdio.h>
int main() {
puts("Error: X");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
因此,您可能不会遇到任何性能问题,具体取决于您的编译器和任何优化...
归档时间: |
|
查看次数: |
4014 次 |
最近记录: |