在C++中通过“把它的名字拼接”来访问变量
假设我有一个变量:在C++中通过“把它的名字拼接”来访问变量,c++,variables,int,C++,Variables,Int,假设我有一个变量: int fish5 = 7; 我可以通过连接术语fish和5来访问fish5吗 理想的解决方案如下所示: printf("I am displaying the number seven: %i", fish + 5); 不,不完全是你想要的。但在您的示例中,仅当您希望将variablename与数字连接在一起时,才可以使用数组: int fish[6] = {0}; fish[5] = 7; printf("I am displaying the number s
int fish5 = 7;
我可以通过连接术语fish和5来访问fish5吗
理想的解决方案如下所示:
printf("I am displaying the number seven: %i", fish + 5);
不,不完全是你想要的。但在您的示例中,仅当您希望将variablename与数字连接在一起时,才可以使用数组:
int fish[6] = {0};
fish[5] = 7;
printf("I am displaying the number seven: %i", fish[5]);
参见C++中的数组引用。
另一种解决方案是使用std::map,正如StruthMaster在评论中指出的那样 然后你可以写一些类似的东西:#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的更多信息::图,参见./P>< P>不可能将解决方案从编译时间转换为运行时间,因为C++是编译语言,不是解释语言。编译后,变量名失去了意义。它们只是一组带有地址的符号。这意味着,在编译之后,要求像fish5这样的东西是没有意义的 为了实现您想要的,您需要以某种编程方式将名称绑定到对象,例如使用一个映射,该映射将名称存储为键,将对象引用存储为值。这就是python的工作方式,也是为什么在python中您可以通过代码中的名称来访问对象 如果有人想知道为什么gdb或崩溃转储是有意义的,原因几乎是一样的。符号名必须在编译时保存在可执行文件或外部文件中,然后外部工具可以确定某个地址下的变量名。但是,如果没有这些信息,编译后的可执行文件可以正常工作 或者,您需要以某种更方便的方式记住引用本身,从而使其具有可计算性。例如,将其储存在阵列中,并作为鱼[5]进入;虽然在本例中,可以在编译时对其求值,但您可以在运行时使用相同的方法,使用变量代替5
编译时和运行时之间的区别非常重要,因为您可以使用预处理器在编译时执行您想要的操作,但这只是因为它是编译时。您只能在编译时使用预处理器执行此操作。完整示例:
#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;
}
然而,这是严格的编译时间。如果尝试JOINfish,fish会出现错误:“fishfish”未声明,如果尝试JOINfish,fish会出现错误:粘贴fish和fish不会给出有效的预处理标记
在C++中,变量名在运行时不存在,所以操作不能在运行时完成,除非一些深调试信息用它们的名称字符串像调试器一样查找变量。若使用字符串对您来说是有效的方法,那个么最好只显式地拥有从字符串到变量地址的映射。其他答案说明了如何通过使用std::map来实现这一点。您可以使用特定于操作系统的东西,如Posix上的Linux,在运行时通过非压缩ELF可执行文件中的符号表访问变量 因此,最好将要访问的变量声明为extern C.g 否则,请考虑特定于编译器的 还声明一个程序句柄:
void *progdlh;
在main中尽早初始化它
然后,要通过计算名称检索变量,可以尝试:
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。这应该适用于运行时还是编译时?编译时可以使用预处理器。在运行时这是不可能的。一个更合理的场景是存储变量fish1、fish2。。。在向量/数组中,并使用索引检索它。鱼[4]将是第五条鱼。将它们存储在一个数组中,并使用索引检索它,请参见康斯坦丁的答案和我的评论here@user3800357:然后向我们展示上下文。全世界的人都在使用cuda,但没有这个问题@user3800357您可能需要添加一些与CUDA部件相关的信息,因为要求不同。@StruthMaster每次存储名称“fish”时都不符合逻辑,为什么不只是存储值并使用向量/列表?@Constantin我也有同样的想法,这就是用户所追求的场景。@StruthMaster谢谢,我还为std::map添加了相同的功能。如果受支持,在此处使用std::unordered_map可能会更好。在运行时,可以使用操作系统特有的技巧通过变量名访问变量。请看我的答案。我认为gdb如何工作部分已经涵盖了这一点,但如果不清楚的话,我可以明确说明。我还认为,依赖这种机制是危险的,或者至少是一种相当可疑的做法,但还是有可能的。+1一般方法是合理的,但在流上使用printf族函数-P
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);