例如,如何避免两次写'func_name'?
#ifndef TEST_FUN # define TEST_FUN func_name # define TEST_FUN_NAME "func_name" #endif
我想遵循单点真相规则.
C预处理器的版本:
$ cpp --version cpp (GCC) 4.1.2 20070626 (Red Hat 4.1.2-14)
Jonathan Lef.. 73
害羞的人*给了你一个答案的细菌,但只有细菌.在C预处理器中将值转换为字符串的基本技术确实是通过'#'运算符,但所提出的解决方案的简单音译会产生编译错误:
#define TEST_FUNC test_func #define TEST_FUNC_NAME #TEST_FUNC #includeint main(void) { puts(TEST_FUNC_NAME); return(0); }
语法错误在'puts()'行上 - 问题是源中的'stray#'.
在C标准的第6.10.3.2节中,"#运营商",它说:
类似函数的宏的替换列表中的每个#preprocessing token都应该跟一个参数作为替换列表中的下一个预处理标记.
麻烦的是你可以将宏参数转换为字符串 - 但是你不能转换非宏参数的随机项.
所以,要达到你想要的效果,你肯定要做一些额外的工作.
#define FUNCTION_NAME(name) #name #define TEST_FUNC_NAME FUNCTION_NAME(test_func) #includeint main(void) { puts(TEST_FUNC_NAME); return(0); }
我不清楚你打算如何使用这些宏,以及你打算如何完全避免重复.这个稍微复杂的例子可能会提供更多信息.使用等效于STR_VALUE的宏是获得所需结果所必需的习惯用法.
#define STR_VALUE(arg) #arg #define FUNCTION_NAME(name) STR_VALUE(name) #define TEST_FUNC test_func #define TEST_FUNC_NAME FUNCTION_NAME(TEST_FUNC) #includestatic void TEST_FUNC(void) { printf("In function %s\n", TEST_FUNC_NAME); } int main(void) { puts(TEST_FUNC_NAME); TEST_FUNC(); return(0); }
*在第一次写这个答案时,shoosh的名字使用'Shy'作为名字的一部分.
害羞的人*给了你一个答案的细菌,但只有细菌.在C预处理器中将值转换为字符串的基本技术确实是通过'#'运算符,但所提出的解决方案的简单音译会产生编译错误:
#define TEST_FUNC test_func #define TEST_FUNC_NAME #TEST_FUNC #includeint main(void) { puts(TEST_FUNC_NAME); return(0); }
语法错误在'puts()'行上 - 问题是源中的'stray#'.
在C标准的第6.10.3.2节中,"#运营商",它说:
类似函数的宏的替换列表中的每个#preprocessing token都应该跟一个参数作为替换列表中的下一个预处理标记.
麻烦的是你可以将宏参数转换为字符串 - 但是你不能转换非宏参数的随机项.
所以,要达到你想要的效果,你肯定要做一些额外的工作.
#define FUNCTION_NAME(name) #name #define TEST_FUNC_NAME FUNCTION_NAME(test_func) #includeint main(void) { puts(TEST_FUNC_NAME); return(0); }
我不清楚你打算如何使用这些宏,以及你打算如何完全避免重复.这个稍微复杂的例子可能会提供更多信息.使用等效于STR_VALUE的宏是获得所需结果所必需的习惯用法.
#define STR_VALUE(arg) #arg #define FUNCTION_NAME(name) STR_VALUE(name) #define TEST_FUNC test_func #define TEST_FUNC_NAME FUNCTION_NAME(TEST_FUNC) #includestatic void TEST_FUNC(void) { printf("In function %s\n", TEST_FUNC_NAME); } int main(void) { puts(TEST_FUNC_NAME); TEST_FUNC(); return(0); }
*在第一次写这个答案时,shoosh的名字使用'Shy'作为名字的一部分.
@Jonathan Leffler:谢谢.你的解决方案有效
一个完整的工作示例:
/** compile-time dispatch $ gcc -Wall -DTEST_FUN=another_func macro_sub.c -o macro_sub && ./macro_sub */ #include#define QUOTE(name) #name #define STR(macro) QUOTE(macro) #ifndef TEST_FUN # define TEST_FUN some_func #endif #define TEST_FUN_NAME STR(TEST_FUN) void some_func(void) { printf("some_func() called\n"); } void another_func(void) { printf("do something else\n"); } int main(void) { TEST_FUN(); printf("TEST_FUN_NAME=%s\n", TEST_FUN_NAME); return 0; }
例:
$ gcc -Wall -DTEST_FUN=another_func macro_sub.c -o macro_sub && ./macro_sub do something else TEST_FUN_NAME=another_func