我们知道结构变量和全局变量的地址是在运行时分配的。 我必须将这些地址传递给一个函数。我只有变量的名称存储在二维数组中。怎么可能这样做?
作为一个例子:有一些文件有全局&结构变量。我已从.map
文件中收集了数组中的所有变量名,但我想确定变量的地址。
答案 0 :(得分:5)
您不能将变量的名称作为字符串并将其转换为地址,这称为内省,标准C没有该设施。
可以做的是提供您自己的映射,例如:
int glob_one, glob_two;
typedef struct {
char *name;
int *addr;
} tMap;
tMap map[] = {
{"glob_one", &glob_one },
{"glob_two", &glob_two },
};
int *findVar (char *key) {
for (int i = 0; i < sizeof(map) / sizeof(map[0]); i++) {
if (strcmp (map[i].name, key) == 0) {
return map[i].addr;
}
}
return NULL;
}
:
int *glob_to_use = findVar ("glob_two");
if (glob_to_use != NULL)
*glob_to_use = 42;
如果您使用的是POSIX系统,dlsym
可以获取有关全局命名空间的信息:
int glob_one;
:
int *glob_to_use = dlsym (RTLD_DEFAULT, "glob_one");
if (glob_to_use != NULL)
*glob_to_use = 42;
例如,以下代码:
#include <stdio.h>
#include <dlfcn.h>
int glob_one;
int main (int argc, char *argv[]) {
int *glob_to_use;
printf ("Old value is %d\n", glob_one);
glob_to_use = dlsym (RTLD_DEFAULT, "glob_one");
if (glob_to_use != NULL)
*glob_to_use = 42;
else
puts (dlerror());
printf ("New value is %d\n", glob_one);
return 0;
}
在Linux下编译时使用:
gcc -rdynamic -o testprog testprog.c -ldl
将产生:
Old value is 0
New value is 42
如果您使用的是Windows而不是POSIX系统,则等效的调用是GetProcAddress()
。以下是与上述相同的程序:
#include <Windows.h>
#include <iostream>
extern "C" {
__declspec(dllexport) int glob_one = 13;
}
int main (void) {
std::cout << "Old value is " << glob_one << '\n';
HMODULE hMod = GetModuleHandle (NULL);
int *pGlobal = (int*) GetProcAddress (hMod, "glob_one");
*pGlobal = 42;
std::cout << "New value is " << glob_one << '\n';
return 0;
}
请注意extern "C"
和dllexport
的使用,这两者都是必需的。第一个停止名称修改,因此您可以使用真实名称进行符号查找。第二个导出变量,以便GetProcAddress()
可以找到它。
与上面的Linux一样,输出显示您可以通过其文本名称访问全局:
pax> gpatest
Old value is 13
New value is 42
答案 1 :(得分:1)
您可以通过它的名称访问变量的地址,如
int globvar = 5; // global
{
int *pglob_myvar = (int *)dlsym(RTLD_NEXT, "globvar");
printf("global: %d\n",*pglob_myvar);
}