通常,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
};
如果您使用的是符合 C99 的 C 版本,您实际上可以使用字段名称初始化结构并让它分配任何类型。但是 Microsoft C 不符合 C99,所以如果你想用float
ordouble
值初始化你的结构,上面是一场噩梦。(如果将浮点值转换为整数,C 不仅会更改类型,还会对值进行四舍五入;而且我知道没有任何技巧可以可移植地获取正确表示 32 位的 32 位整数值在 C 程序的编译时浮动。)
编译时浮动包装/双关语
但是,如果您使用指针,那很容易。只需将联合中的第一个字段名称设置为指针类型,将指针转换void *
为上面的结构并初始化结构(指针将转到1234
上面的位置)。
如果您正在阅读由其他人的代码编写的表格,并且您没有办法添加类型标识符字段,那么我没有给您一个通用的答案。我想您可以尝试将指针读取为不同的类型,然后看看哪些有效?