关于具有唯一整数id的指针的并集的安全性 拐角案例

问题描述

typedef union {void *ptr; int id;} handle;

这不安全,对吗?

我看到一个唯一的ID是基于64位指针的内存位置 value 的。然后,可以使用唯一的ID进行匹配,反之亦然,可以在匹配的“ ID”上使用指针。

这似乎还可以,但我想问一下专业人士。

(供参考)我在nuklear.h(单个头文件gui库)中注意到了这一点。

https://github.com/Immediate-Mode-UI/Nuklear

解决方法

工会本身非常安全。

通过写入联合的一个元素,然后读取另一个元素来使用联合进行类型修剪……不是那么安全。

类型

如果您想要一个可以容纳指针的整数,通常需要使用uintptr_tintptr_t而不是int

操作

但这可能是不必要的。至少从事物的声音来看,您只需要一个值即可使您唯一地标识一个对象,并且能够比较指向对象的两个引用/指针是真的引用相同还是不同的对象。假设是这种情况,您根本不需要转换为整数,只需将地址存储在指针中并进行比较即可。比较不平等时,即使对于不相关的对象,您也可以获得有意义的结果。这是C ++标准的措辞:

(3.1)—如果一个指针代表一个完整对象的地址,而另一个指针代表另一个完整对象的最后一个元素之后的地址,则比较结果不确定。
(3.2)—否则,如果指针都为null,都指向同一函数或都表示相同的地址(6.8.2),则它们比较相等。
(3.3)—否则,指针比较不相等。

因此,指向同一对象的两个指针比较相等。指向不同对象的两个指针比较不相等。不必完全转换为整数类型就可以得到那么多(C语言中也是如此)。

拐角案例

该(3.1)的第一条款可能需要更多解释。您可以创建一个指向数组末尾的指针,并且可以将其与同一数组中的其他指针进行比较(要求比任何一个都更大)。但是,在极端情况下,未指定结果。考虑:

int a[4];
int b;

if (a+4 == b) {
    ...
}

在这种情况下,a+4可能等于或可能不等于b。不能保证任何一种方式。但是请记住,a+4是一个不能取消引用的指针,它不是指向对象的指针。指向任何对象的指针都不会落入这种极端情况。

如果要在指针之间进行排序,因此可以比较类似a < b之类的东西,那么事情会变得有些混乱,并且在C和C ++之间有所不同。在C语言中,执行此操作的唯一方法是(如上所述)将每个指针转换为intptr_t(或uintptr_t)并进行比较。请注意,每次转换必须进行一次,并永久存储结果,因为不能保证转换的稳定性。

在C ++中,即使它们不相关,也可以使用std::less比较排序的指针,因此直接使用a < b不会产生有意义的结果。给定一些不相关的对象ab,它不能保证它们的顺序,但是可以保证结果是一致的(重新进行相同的比较将始终得出相同的结果)和可传递(因此,如果a<bb<c,则为a<c)。

摘要

至少基于您在问题中概述的内容,这听起来似乎根本没有任何理由要转换为整数。除非您需要您没有谈论过的东西,否则只需存储并比较地址即可,您就很好。