将 void * 值设置为 intptr_t 变量是否需要显式转换?

Does setting a void * value to a intptr_t variable require an explicit cast?

我似乎无法理解当我尝试将 void * 值分配给 intptr_t 变量时收到的 GCC 编译器警告。具体来说,当我使用 -std=c99 -pedantic 进行编译时,我在第 7 行收到有关变量 z 初始化的以下警告:

warning: initialization makes integer from pointer without a cast [-Wint-conversion]

这里是源代码:

#include <stdint.h>

int main(void){
        unsigned int x = 42;
        void *y = &x;

        intptr_t z = y; /* warning: initialization makes integer from pointer without a cast [-Wint-conversion] */

        return 0;
}

当然,如果我明确地将 y 转换为 intptr_t,那么警告就会消失。但是,当 intptr_t 的全部目的在于 void * 值的转换和操作时,我很困惑为什么会出现隐式转换警告。

来自 C99 标准的 7.18.1.4 部分:

The following type designates a signed 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:

intptr_t

我是否误解了标准,或者 GCC 在这种情况下的“来自指针的整数”检查中是否过于迂腐?

总结一下!如有任何错误,请提前致歉 - 请给我留言。

在 C99 中:

  • 任何指针都可以转换为整数类型。1
  • 您可能想要这样做,例如 if you are implementing your own operating system!
  • 指针和整数之间的转换可能会出错,1 通常 也不是您想要的。
  • 因此,当您将指针转换为整数而不进行强制转换时,编译器会发出警告。这并不过分迂腐,但可以避免您出现未定义的行为。
  • intptr_t(和uintptr_t,同样贯穿始终)只是一个整数类型,2因此它与任何其他类型一样面临相同的风险指针到整数的转换。因此,您会收到相同的警告。
  • 但是,使用intptr_t,您至少知道从指针的转换不会截断任何位。因此,如果您确实需要指针的整数值,那么这些就是要使用的类型 - 显式转换。

    • 规范1,#6

      ... the result is implementation-defined. If the result cannot be represented in the integer type, the behavior is undefined.

      加上intptr_t,结果可以用整型表示。因此,该行为不是未定义,而仅仅是实现定义的。这就是(据我所知)为什么这些类型可以安全地用于从指针接收值。

编辑

下面的参考文献 1 是第 6.3 节的一部分,"Conversions." 规范说:3

Several operators convert operand values from one type to another automatically. This subclause specifies the result required from such an implicit conversion...

并参考第 6.5.4 节讨论显式强制转换。因此,参考文献 1 中的讨论确实涵盖了从任何指针类型到 intptr_t 的隐式转换。根据我的阅读,从 void *intptr_t 的隐式转换是合法的,并且具有实现定义的结果。1, 4

关于显式转换是否应该gcc -pedantic认为应该,而且必须有充分的理由! :) 我个人同意显式转换更清晰。我也认为代码应该尽可能在没有警告的情况下编译,所以如果它是我的代码,我会添加显式转换。

参考文献

1C99 draft(因为我没有最终规范的副本),秒。 6.3.2.3 #5 和 #6).

2Id.,秒。 7.18.1.4

3Id.,秒。 6.3

4Id.,秒。 3.4.1、将"implementation-defined behavior"定义为"unspecified behavior where each implementation documents how the choice is made." 言下之意是转换是合法的,但在一个平台上的结果可能与在另一个平台上的结果不同。