说我有一些C代码,如:
#define FOO 2
#define BAR 3
#define BAZ 500
void get_value(int val) {
printf("The value is %s\n", some_function_or_macro_or_something(val));
}
int main(int argc, char** argv) {
get_value(BAZ);
get_value(FOO);
return 0;
}
我希望它打印出来 "价值是BAZ" 和 "值为FOO"。但是有成千上万的#defines,所以我想以编程方式进行。
答案 0 :(得分:3)
C绝对能够使用#
字符串化运算符执行此操作,但您需要直接使用标识符调用宏:
#include <stdio.h>
#define FOO 2
#define BAR 3
#define BAZ 500
#define get_value(val) \
printf("The value is %s\n", #val);
int main(void)
{
get_value(BAZ);
get_value(FOO);
return 0;
}
在传递例如值之后的示例中BAZ
到get_value
函数,标记BAZ
不再被识别,因为参数是按值传递的。换句话说,宏标识符已经消失(当然你仍然可以对其替换进行字符串化,请参阅下面的评论)。
这是一个小服从这个&#34;顶级&#34;规则。假设您有少量具有唯一值的类似对象的宏(常量),那么您可以执行以下操作:
#include <stdio.h>
#define FOO 2
#define BAR 3
#define BAZ 500
#define STRINGIFY(val) #val
void get_value(int val) {
switch (val) {
case FOO :
printf("The value is %s\n", STRINGIFY(FOO)); break;
case BAR :
printf("The value is %s\n", STRINGIFY(BAR)); break;
case BAZ :
printf("The value is %s\n", STRINGIFY(BAZ)); break;
}
}
int main(int argc, char* argv) {
get_value(BAZ);
get_value(FOO);
return 0;
}
结果:
The value is BAZ
The value is FOO
答案 1 :(得分:0)
使用正确的工具完成工作。哪个工具知道宏的全部内容?编译器。 GNU gcc和clang都允许转储已定义的宏列表:
$ cc -E -dM -x c /usr/include/stdio.h
#define BUFSIZ 1024
#define EOF (-1)
#define FILENAME_MAX 1024
#define FOPEN_MAX 20
#define L_ctermid 1024
#define L_cuserid 17
#define L_tmpnam 1024
#define NULL ((void *)0)
#define P_tmpdir "/tmp/"
#define SEEK_CUR 1
#define SEEK_END 2
#define SEEK_SET 0
/* etc */
将列出由<stdio.h>
定义的整个shebang及其包含的所有内容。
如果需要在C程序中以编程方式处理此数据,
#include <stdio.h>
#define BIG_ENOUGH 1024
int main (void)
{
char buffer[BIG_ENOUGH];
FILE *fp = popen ("cc -E -dM -x c /usr/include/stdio.h", "r");
while (fgets(buffer, sizeof buffer, fp) != NULL) {
char identifier[BIG_ENOUGH];
int value;
if (sscanf (buffer, "#define %s %d", identifier, &value) == 2) {
printf ("value %d is from macro %s\n", value, identifier);
}
}
fclose(fp);
return 0;
}
这里打印stdio.h
value 1024 is from macro BUFSIZ
value 1024 is from macro FILENAME_MAX
value 20 is from macro FOPEN_MAX
value 1024 is from macro L_ctermid
value 17 is from macro L_cuserid
value 1024 is from macro L_tmpnam
value 1 is from macro SEEK_CUR
value 2 is from macro SEEK_END
value 0 is from macro SEEK_SET
value 308915776 is from macro TMP_MAX
[...]
而不是stdio.h
,您只需使用file.c
作为输入。
答案 2 :(得分:0)
经典的,如果有点重量级的方法是表格文件:
enum.tab:
#ifndef DECL_CONST
# define DECL_CONST(name, value)
#endif
DECL_CONST(FOO, 2)
DECL_CONST(BAR, 3)
DECL_CONST(BAZ, 500)
#undef DECL_CONST
enum.h:
enum My_Enum
{
#define DECL_CONST(name, value) name = value,
#include "enum.tab"
};
char const* get_name(enum My_Enum value);
enum.c:
#include "enum.h"
char const* get_name(enum My_Enum value)
{
switch (value)
{
#define STR(name) #name
#define DECL_CONST(name, value) case value: return STR(name);
#include "enum.tab"
default:
return 0;
}
}
main.c中:
#include "enum.h"
void process_value(int v)
{
char const* s = get_name((enum My_Enum) v);
if (s)
printf("The name of value %d is %s\n", v, s);
else
printf("There is no name for value %d\n", v);
}
int main()
{
process_value(1);
process_value(2);
process_value(3);
process_value(500);
process_value(501);
return 0;
}
当然,您可以扩展此基本方案以包含任意数量的属性,并支持它们之间的任意数量的依赖关系。请注意,如果您为同一个值定义了多个名称,则switch
语句的编译将失败。
答案 3 :(得分:-1)
不确定是否可行。海湾合作委员会在their manual中说明:
无法将宏参数转换为字符常量。