我正在开发一个系统(虚拟机?不知道如何调用它),其中每个数据结构都是一个数组(或结构),开头有三个整数字段(必须在一个接一个的开头,没有填充字节)和n通用指针。我对此想了很多,但似乎很难找到一个明确的解决方案。
下面是我的第一次尝试。
void **a = malloc(SOME_SIZE);
a[0] = (void *)1;
a[1] = (void *)0;
a[2] = (void *)1;
a[3] = malloc(SOME_SIZE); a[4] = malloc(SOME_SIZE); //and so on...
我在这里不确定void *
转换为整数是否安全。经过一番研究,我将代码更改如下。
void **a = malloc(SOME_SIZE);
*(uintptr_t *)a = 1;
*((uintptr_t *)a + 1) = 0;
*((uintptr_t *)a + 2) = 1;
a[3] = malloc(SOME_SIZE); a[4] = malloc(SOME_SIZE); //and so on...
但后来我发现,在某些平台上,sizeof(void *)
可能不等于sizeof(uintptr_t)
。所以我决定把它改成一个结构。
typedef struct data {
size_t counts[3]; //padding bytes are okay after this line
void *members[]; //flexible array member
} *data;
data a = malloc(sizeof(*a) + SOME_SIZE);
a->counts[0] = 1;
a->counts[1] = 0;
a->counts[2] = 1;
a->members[0] = malloc(SOME_SIZE); a->members[1] = malloc(SOME_SIZE); //and so on...
在这里,我发现了一个问题,即C中没有100%可移植的通用指针,但我找不到解决方案,所以让我忽略一些具有不同指针大小的wierd平台。
既然void *
可以存储指向任何对象的指针,那么我的最后一个解决方案是否满足了我的目的?我不太熟悉灵活的数组成员,所以我可能犯了一个错误。或者可能还有一些我遗漏了。
感谢您的帮助。
您可以使用单个void*
数组,将它们强制转换为uintptr_t
以获得它们的整数值。
uintptr_t
是能够存储指针的无符号整数类型。请参阅什么是uintptr_t数据类型。
请记住,这是一个非常丑陋、难以阅读和危险的把戏。
假设您有一些方法可以知道哪些东西是整数,哪些是指针,那么您可以合法地使用union
,它将整数和指针组合在一起。在所讨论的整数类型没有填充位或陷阱表示的系统上,存储指针然后读回整数应该总是产生一个值(而不是导致未定义的行为),但所讨论整数的值应该被认为是无意义的。即使整数类型恰好是uintptr_t
,我认为也不能保证类型punning是在指针类型和整数类型之间转换的合法方式。
存储一个整数值然后读取指针肯定是未定义的。整数值的行为不是通过读取合法指针来读取的。如果有一个uintptr_t
是通过对合法指针进行类型双关获得的,那么使用类型双关将该值转换回指针可能会起作用,但我不知道是否指定了它。我不认为将这样的整数强制转换为指针类型会起作用,也不认为可以在通过强制转换获得的uintptr_t
上使用类型punning。