我不知道如何解释我现在遇到的问题,如果我对问题的标题含糊不清,我深表歉意。
我现在拥有的是存储在变量中的虚拟地址列表。例如,我有
0x8c334dd
存储在一个 char 变量中。这个地址是另一个有数据的变量的地址。我想做的是转到该地址并获取存储在其中的数据。
我的假设是解除对指针的引用是最好的方法,不幸的是我不知道地址指向的变量的类型,那么在这种情况下解除引用是如何工作的呢?我不能这样做:*(char *) 8c334dd
因为我不知道地址指向的变量的类型...
如果我将其转换为 (int *)
,我会得到某些地址指向的某些变量的一些数据(记住我有多个地址),但对于其他地址,我是只是得到一个地址,我需要数据(这个变量是结构、字符等)。
我正在使用 ELF 符号表
最佳答案
通常,C++ 或 C 无法知道您拥有的指针类型。
通常解决这个问题的方法是让指针指向一个结构体,并在结构体中有一个已知的位置来指示数据的类型。通常已知位置是结构中的第一个位置。
例子:
// signature value; use any value unlikely to happen by chance
#define VAR_SIG 0x11223344
typedef enum
{
vartypeInvalid = 0,
vartypeInt,
vartypeFloat,
vartypeDouble,
vartypeString,
vartypeMax // not a valid vartype
} VARTYPE;
typedef struct
{
VARTYPE type;
#ifdef DEBUG
uint32_t sig;
#endif // DEBUG
union data
{
int i;
float f;
double d;
char *s;
};
} VAR;
然后您可以进行健全性检查:您可以查看 type
字段的值是否大于 vartypeInvalid
且小于 vartypeMax
(并且您永远不需要在健全性检查代码中编辑这些名称;如果您添加更多类型,则将它们添加到列表中的 vartypeMax
之前)。此外,对于 DEBUG
构建,您可以检查签名字段 sig
是否包含一些特定的签名值。 (这意味着您初始化 VAR
实例的初始化代码当然需要始终设置 sig
字段。)
如果你做这样的事情,那么你如何初始化它?运行时代码将始终有效:
VAR v;
#ifdef DEBUG
v.sig = VAR_SIG;
#endif // DEBUG
v.type = vartypeFloat;
v.data = 3.14f;
如果想在编译时初始化怎么办?如果你想用整数值初始化它很容易,因为 int
类型是 union
中的第一个类型:
VAR v =
{
vartypeInt,
#ifdef DEBUG
VAR_SIG,
#endif // DEBUG
1234
};
如果您使用的是 C 的 C99 兼容版本,您实际上可以使用字段名称初始化结构并让它分配任何类型。但是 Microsoft C 不兼容 C99,因此如果您想使用 float
或 double
值初始化您的结构,以上内容将是一场噩梦。 (如果将浮点值转换为整数,C 不仅会更改类型,还会对值进行四舍五入;而且据我所知,没有任何技巧可移植地获得正确表示 32 位的 32 位整数值在 C 程序的编译时 float 。)
Compile time float packing/punning
不过,如果您使用的是指针,那很容易。只需将 union 中的第一个字段名称设为指针类型,将指针转换为 void *
并如上所述初始化结构(指针将指向 1234
上面的位置) .
如果您正在阅读由其他人的代码编写的表格,并且您没有办法添加类型标识符字段,那么我没有给您一个通用的答案。我想您可以尝试将指针读出为不同的类型,然后看看哪些有效?
关于c++ - 取消引用指向未知类型变量的指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12466485/