是否有任何用例依赖于两个分配的整数表示在C中是不同的?

例如,请考虑以下C代码段:

void *p = malloc(1); void *q = malloc(1); bool question = (uintptr_t) p == (uintptr_t) q; 

我希望每个人都希望question永远是假的。 (令人惊讶的是,C11标准并不要求它。对uintptr_t的唯一限制是例如((void *) ((uintptr_t) p)) == p 。有关详细信息,请参阅C11标准的7.20.1.4。)

我的问题是:是否有任何实际用例实际上依赖于保证question是错误的,或者更一般地说,两个分配的整数表示是不同的?

这个问题有缺陷。 首先,考虑一下这段代码(我们假设malloc不返回null):

 void *p = malloc(1); void *q = malloc(1); bool question = (uintptr_t) p == (uintptr_t) q; 

根据C 2011标准的uintptr_t规范,如果我们这样做:

 void *p1 = (void *) (uintptr_t) p; void *q1 = (void *) (uintptr_t) q; 

那么p1必须比较等于pq1必须比较等于q 。 并且,根据==运算符的标准规范, p1q1不能相互比较,因为它们分别等于pq ,因此是指向不同对象的指针。

因为(void *) (uintptr_t) p(void *) (uintptr_t) q产生不同的值, (uintptr_t) p(uintptr_t) q必须是不同的值。 (这是因为转换为void *是C模型中的一个数学函数。每次给定一个特定值,在C的规则内,它产生的结果实际上是相同的,在C的规则内。)因此(uintptr_t) p不等于(uintptr_t) q

现在考虑这个代码,我们将void *更改为char *

 char *p = malloc(1); char *q = malloc(1); bool question = (uintptr_t) p == (uintptr_t) q; 

uintptr_t的规范没有提及char *转换。 显然,这些指向char *指针可以转换为void * 。 但是,我没有看到标准要求从char *uintptr_t必须隐式地将转换插入void *或者就像它一样。 所以我认为这在标准上在技术上是不确定的。 但是我怀疑你会发现任何与void *版本不同的C实现,除了一个专门构造违反这个的实现。

尽管如此,有效地使用uintptr_t每个程序员都希望结果完全识别原始指针(它包含要转换回原始指针的所有信息),因此他们期望uintptr_t结果与所有不同指针的结果不同。

至于一个具体的例子,macOS中的Accelerate框架期望将不同指针转换为uintptr_t结果产生不同的结果,我相信macOS的许多其他部分也会这样做。