通过"拼接"访问C ++中的变量它的名字在一起

时间:2014-07-03 06:26:55

标签: c++ variables int

我们说我有一个变量:

 int fish5 = 7;

我可以通过连接术语" fish"来访问fish5。和" 5"不知何故?

理想的解决方案看起来像这样:

 printf("I am displaying the number seven: %i", fish + 5);

4 个答案:

答案 0 :(得分:4)

不,不完全是你想要的。但在您的示例中,您可以使用数组(仅当您要将变量名称与数字连接时才有效):

int fish[6] = {0};
fish[5] = 7;

printf("I am displaying the number seven: %i", fish[5]);

另请参阅here以获取对C ++中的数组的引用。

另一种解决方案是使用std::map代替,就像Thrustmaster在评论中指出的那样。

然后你可以这样写:

#include <map>
#include <string>

int main(int argc, char* argv[]){
  std::map<std::string, int> map;
  map.insert(std::make_pair("fish5", 7));
  printf("I am displaying the number seven: %d", map[std::string("fish") + std::to_string(5)]);
  return 0;
}

有关std::map的详细信息,请参阅here

答案 1 :(得分:2)

将解决方案从编译时转换为运行时是不可能的,因为c ++是一种编译语言,而不是解释的语言。变量名称在编译后“失去意义”。它们只是一组带地址的符号。这意味着,在编译后要求fish5这样的东西没有任何意义。

要实现您想要的功能,您需要以某种方式以编程方式将名称绑定到对象,例如使用映射,将名称存储为键,将对象引用存储为值。这就是python的用法,以及为什么在python中你可以通过代码中的名字实际访问对象。

如果有人想知道为什么例如gdb或崩溃转储是有意义的,那也是出于同样的原因。符号名称必须在编译时保存(嵌入在可执行文件或外部文件中),然后外部工具可以确定某个地址下变量的名称。但是编译后的可执行文件可以很好地处理这些信息。

或者,您需要以更方便的方式记住引用本身,这允许它是可计算的。例如。将其存储在数组中并以fish[5]进行访问;虽然在此示例中可以在编译时对其进行评估,但您可以在运行时使用相同的方法,使用变量代替5

编译时和运行时之间的区别非常重要,因为您可以在编译时使用预处理器实际执行所需的操作,但这只是因为它是编译时。

答案 2 :(得分:2)

您可以使用特定于操作系统的东西,例如(在Posix,例如Linux上)dlsym(3),以便在运行时通过(未提取的)ELF可执行文件内的符号表访问变量。

因此,最好通过名称extern "C"声明要访问的变量,例如

 extern "C" int fish17;

(否则,请考虑编译器特定的name mangling

还声明一个程序句柄:

 void *progdlh;

main

中尽早初始化它
 progdlh = dlopen(NULL, RTLD_NOW|RTLD_GLOBAL);
 if (!progdlh) { fprintf(stderr, "dlopen failure %s\n", dlerror()); 
                 exit(EXIT_FAILURE); }

然后,要通过计算名称检索变量,您可以尝试:

 char nambuf[32];
 snprintf (nambuf, sizeof(nambuf), "%s%d", "fish", 17);
 int *pvar = dlsym(progdlh, nambuf);
 if (!pvar) { fprintf(stderr, "dlsym %s failure %s\n", nambuf, dlerror()); 
                 exit(EXIT_FAILURE); }
 printf ("variable %s is %d\n", nambuf, *pvar);

您可能应该将您的程序与-rdynamic标记(以及-ldl库)链接

我的回答应该适用于Linux。

答案 3 :(得分:0)

您只能在编译时使用预处理器执行此操作。完整的例子:

#include <cstdio>

#define JOIN(a,b) a##b

int main(void) {
    int fish5 = 5;
    std::printf("I am displaying the number five: %i", JOIN(fish, 5));
    return 0;
}

但是,这是严格的编译时间。如果您尝试JOIN(fish, fish),则会获得error: ‘fishfish’ undeclared,如果您尝试JOIN("fish", fish),则会获得error: pasting ""fish"" and "fish" does not give a valid preprocessing token

在C ++中,变量名在运行时不存在,因此操作不能在运行时完成,除非一些深度调试信息通过其名称字符串查找变量(就像调试一样)。如果使用字符串对您来说是有效的方法,那么最好只显示从字符串到变量地址的映射。其他答案显示了如何使用std::map

执行此操作