C程序将变量名称作为输入和打印值

时间:2014-08-08 07:40:35

标签: c gcc

我有一个程序test.c

int global_var=10;
printf("Done");

我做了

gcc -g test.c -o test

我的查询是 有没有办法可以将变量名称作为参数(例如" global_var")并打印该值。

由于

4 个答案:

答案 0 :(得分:3)

不,C没有introspection。一旦编译器生成了代码,程序就无法查找变量名。

通常解决这些问题的方法是通过拥有需要按名称查找的所有特殊变量的集合,包含实际名称和字符串变量。

通常它是一组结构,比如

struct
{
    const char *name;
    int value;
} variables[] = {
    { "global_var", 10 }
};

然后,程序可以查看数组variables以搜索"global_var"并使用(或更改)结构中的值。

答案 1 :(得分:2)

没有。 我们只有变量名称,所以人类不会感到困惑。 将程序转换为程序集并最终转换为机器代码后,计算机并不关心您为变量命名的内容。

或者,您可以使用将值和名称存储为字符串的结构:

struct tag_name {
   char *member1;
   int member2;
};

答案 2 :(得分:2)

一般答案:不可以。变量名和它的字符串表示之间没有联系(你可以在编译时用预处理器获取变量名的字符串表示)。

对于具有外部链接的标识符,有(平台相关的)方式:参见例如POSIX系统的dlsym

您可以使用调试信息进行编译,并通过输入中的名称访问(大多数)变量。除非你真的写了类似调试器的东西,否则这将是一个糟糕的设计(即使这样,你也不会访问调试器本身使用的变量,而是调试正在调试的程序)。

最后,您可以实现自己的查找表映射,从字符串表示到值。

答案 3 :(得分:1)

通常,无法通过名称在运行时访问全局变量。有时,它可能取决于操作系统以及如何调用编译器。我仍然假设您要取消引用全局变量,并且您知道它的类型。

然后在Linux和其他一些系统上,您可以使用dlopen(3)NULL路径(获取可执行文件的句柄),然后在全局变量名称上使用dlsym得到它的地址;然后,您可以将void*指针强制转换为适当类型的指针并取消引用它。请注意,您需要知道类型(或至少有一个约定来在其名称中对变量的类型进行编码; C ++正在使用name mangling)。如果您使用调试信息进行编译和链接(即使用gcc -g),则类型信息位于DWARF可执行文件的ELF部分中,因此可以通过某种方式获取它。

如果您使用-rdynamic-ldl

链接可执行文件,则此方法有效

另一种可能性是使用您自己的GCC扩展程序自定义最近的MELT,该扩展程序会记住并稍后重新使用某些编译器内部表示形式(即与全局相关的GCC Tree-s变量)。使用MELT register_finish_decl_first函数在声明上注册处理程序。但这需要一些工作(编写MELT扩展名)。


使用预处理器技巧

您可以使用(便携式)预处理器技巧来实现目标(在运行时按名称访问变量)。

最简单的方法可能是定义和遵循您自己的约定。例如,您可以拥有自己的globvar.def标题文件,其中只包含

等行
 /* file globvar.def */
 MY_GLOBAL_VARIABLE(globalint,int)
 MY_GLOBAL_VARIABLE(globalint2,int)
 MY_GLOBAL_VARIABLE(globalstr,char*)
 #undef MY_GLOBAL_VARIABLE

您采用的惯例是所有全局变量都在上面的globvar.def文件中。然后你会多次#include "globvar.def" 。例如,在您的全局标题中,将MY_GLOBAL_VARIABLE展开为某个extern声明:

 /* in yourheader.h */
 #define MY_GLOBAL_VARIABLE(Nam,Typ) extern Typ Nam;
 #include "globvar.def"

在你的main.c中,你需要一个类似的技巧声明你的全局。

在其他地方,您可以定义一个函数来按名称获取整数变量:

 /* return the address of  global int variable or else NULL */
 int* global_int_var_by_name (const char*name) {
    #define MY_GLOBAL_VARIABLE(Nam,Typ) \
      if (!strcmp(#Typ,"int") && !strcmp(name,#Nam)) return (int*)&Nam;
    #include "globvar.def"
      return NULL;
 }

等等......我正在使用stringification个宏参数。

这样的预处理器技巧纯粹是标准C,适用于任何符合C99标准的编译器。