有两个相关的C标准规则:
C99标准, 6.3.2.3
:
指向void的指针可以转换为指向any的指针
不完整或对象类型。指向任何不完整或对象类型的指针
可以转换为指向void的指针,然后再返回;结果应该
比较等于原始指针。
和 7.20.1.4
:
以下类型指定带有的无符号整数类型
可以将任何有效指向void的指针转换为此类型的属性,
然后转换回指向void的指针,结果将进行比较
等于原始指针:
uintptr_t
这意味着,以下代码符合:
int *p = NULL;
void *q = (void*)p;
uintptr_t s = (uintptr_t)q;
但它真的需要两步演员吗?如果执行以下操作,编译器是否会执行隐式中间转换:
int *p = NULL;
uintptr_t s = (uintptr_t)p;
(好吧,它可能会出现在大多数编译器上,但我的问题是标准符合性)
我不会冒险。该标准清楚地表明了允许的内容和不允许的内容。
写作 uintptr_t s = (uintptr_t)(void*)p;
向你的代码的读者发出信号,告诉你你正在做什么。
任何高质量的通用实现都将处理之间的转换 uintptr_t
和非虚空类型,好像它们已被转换通过 void*
。
标准将这种情况下的行为以及涉及指针的许多其他行为视为实施质量问题,并期望那些寻求编写高质量实现的人能够识别出有一种明显,明智和有用的方式的情况。对于程序在没有标准必须明确枚举它们的情况下的行为。他们还认识到,有可能产生一种符合但质量很差的实施方案,以至于无用。
虽然有可能实现转换之间的转换 uintptr_t
并且任何非void指针类型都以实现者选择的任意方式运行,任何产生实现的人都应该被认为是这种转换不能以典型的方式工作,并且没有记录这种差异的充分理由。一个破坏者,他们试图通过低质量的实施来破坏语言。程序员应该没有义务安抚这种行为;除非或直到它被看作是什么,它将变得越来越糟,直到语言变得完全无用。