c - 在将指针转换为 `void *` 之前是否需要转换为 `uintptr_t`,反之亦然?

标签 c casting language-lawyer c99 void-pointers

C99 标准的 7.18.1.4 部分指出:

The following type designates an unsigned integer type with the property that any valid pointer to void can be converted to this type, then converted back to pointer to void, and the result will compare equal to the original pointer:

uintptr_t

这是否意味着只有 void * 类型可以在不改变原始指针值的情况下转换为 uintptr_t 并返回?

特别是,我想知道使用 uintptr_t 是否需要以下代码:

int foo = 42;
void * bar = &foo;
uintptr_t baz = bar;
void * qux = baz;
int quux = *(int *)qux; /* quux == foo == 42 */

或者如果 C99 标准保证这个更简单的版本产生相同的效果:

int foo = 42;
uintptr_t bar = &foo;
int baz = *(int *)bar; /* baz == foo == 42 */

在将指针转换为 uintptr_t 之前是否需要转换为 void *,反之亦然?

最佳答案

区别还存在,因为虽然任何指向 对象 的指针都可以转换为 void *,但 C 并不要求函数指针可以转换为 void * 再回来!

至于指向其他类型对象的指针,C标准说任何指针都可以转换为整数,整数也可以转换为任意指针,但这样的结果是实现定义的.因为标准规定只有 void * 可以来回转换,所以最安全的做法是首先转换指向 void * 的指针,因为它可能是当转换为 uintptr_t 时具有不同表示的指针也会导致不同的整数表示,因此可以想象:

int a;
uintptr_t up = (uintptr_t)&a;
void *p = (void *)up;
p == &a; // could be conceivably false, or it might be even that the value is indeterminate.

关于c - 在将指针转换为 `void *` 之前是否需要转换为 `uintptr_t`,反之亦然?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45352226/

相关文章:

c++ - 为什么 “types may not be defined in parameter types”

c - 为什么不指向 VLA 函数参数的指针自动推导它们的大小,目前有什么好的用法吗?

c - 如何用 `1234567890` 打印 `1 2 3 4 5 6 7 8 9 0` 到 `C` ?

启用优化后,代码运行速度提高了一个数量级。我错过了什么吗?

c - 是否有可能在 C 中为 Rf_eval R 捕获错误?

c - 位流在C中保存为uint8_t

PostgreSQL-错误 : column "date" cannot be cast to type date

swift - 为什么我不能在Swift中将(String)-> String转换为(Any)-> Any?

c - 一个字节的位数是否等于一个字符类型的位数?

c++ - 将基类模板的 `this` 类型转换为其派生类