在 C 中存储整数和通用指针的最便携方法是什么?

What is the most portable way to store both integers and generic pointers in C?

我正在开发一个系统(虚拟机?不知道怎么称呼它),其中每个数据结构都是一个数组(或结构),开头有三个整数字段(必须在开头紧接着另一个没有填充字节)和 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% 可移植的通用指针,但是我找不到解决方案,所以让我忽略一些指针大小不同的奇怪平台。

那么鉴于 void * 可以存储指向任何对象的指针,我最后的解决方案是否满足我的目的?我不太熟悉灵活的数组成员,所以我可能犯了一个错误。或者我可能还有一些遗漏的地方。

感谢任何帮助。

您可以使用 void* 的单个数组,将它们转换为 uintptr_t 以获得它们的整数值。

uintptr_t是一个无符号整数类型,可以存储指针。 参见 What is uintptr_t data type

请记住,这是一个非常丑陋、不可读且危险的技巧。

假设您有一些方法知道哪些是整数,哪些是指针,您可以合法地使用 union,它结合了整数和指针。在所讨论的整数类型没有填充位或陷阱表示的系统上,存储一个指针然后读回一个整数应该总是产生一个值(而不是导致未定义的行为)但是应该考虑所讨论的整数的值无意义的。即使整数类型恰好是 uintptr_t,我认为也不能保证类型双关是指针类型和整数类型之间转换的合法手段。

存储一个整数值然后读取指针肯定是未定义的行为整数值不是可以通过读取合法指针来读取的行为。如果一个 uintptr_t 是通过对合法指针进行类型双关获得的,则使用类型双关将该值转换回指针可能会起作用,但我不知道它是否已指定。我不希望将这样的整数转换为指针类型会起作用,也不希望对通过转换获得的 uintptr_t 使用类型双关。