C程序以输入变量名,并打印其值。
在一般情况下,不可能通过变量名在运行时访问全局变量。有时,这可能取决于操作系统和编译器的调用方式。假设您仍然想要解引用全局变量,并且知道其类型。
然后在Linux和其他一些系统上,您可以使用dlopen(3)与NULL
路径(以获取可执行文件的句柄),然后使用dlsym
在全局变量名称上获取其地址;然后,您可以将void*
指针转换为适当类型的指针并对其进行解引用。请注意,您需要知道类型(或至少在名称中编码变量的类型的约定;C++正在使用名称修饰)。如果您使用调试信息(即使用gcc -g
编译和链接),则类型信息位于您的ELF可执行文件的DWARF部分中,因此有一些方法可以获取它。
这适用于使用-rdynamic
链接可执行文件并使用-ldl
的情况。
另一种可能性是使用您自己的MELT扩展自定义最新版本的GCC,该扩展将记住并稍后重新使用一些编译器内部表示(即与全局变量相关的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
中,您需要类似的技巧来声明全局变量。
另外,您可以定义一个通过名称获取整数变量的函数:
/* 返回全局int变量的地址,否则返回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; }
等等... 我正在使用宏参数的字符串化。
这种预处理器技巧纯粹是标准的C,并且可以在任何符合C99标准的编译器上工作。