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

时间:2016-10-13 19:23:07

标签: c pointers gcc c99 gcc-warning

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

  

警告:初始化从指针生成整数而没有强制转换[-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 部分:

  

以下类型指定带有任何有效属性的有符号整数类型   指向 void 的指针可以转换为此类型,然后转换回指向 void 的指针,   并且结果将与原始指针进行比较:

     

使用intptr_t

我是否误解了标准,或者GCC在指针&#34;&#34; 整数中过于迂腐?检查这种情况?

1 个答案:

答案 0 :(得分:3)

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

在C99:

  • 任何指针都可以转换为整数类型。 1
  • 您可能希望这样做,例如if you are implementing your own operating system!
  • 指针和整数之间的转换可能非常错误, 1 所以通常不是你想要的。
  • 因此,编译器会在没有强制转换的情况下将指针转换为整数时发出警告。这不是过于迂腐,而是为了避免未定义的行为。
  • intptr_t(和uintptr_t,同样在整个过程中)只是一个整数类型, 2 因此它与任何其他指针到整数的风险相同转换。因此,您会得到相同的警告。
  • 然而intptr_t,您至少知道指针的转换不会截断任何位。所以这些是要使用的类型 - 使用显式强制转换 - 如果确实需要指针的整数值。

    • 规范 1,#6 表示

        

      ......   结果是实现定义的。如果结果无法以整数类型表示,   行为未定义。

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

修改

下面的参考文献1是第6.3节“转换”的一部分。规范说: 3

  

多个运算符自动将操作数值从一种类型转换为另一种类型。这个   子条款指定了这种隐式转换所需的结果......

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

关于是否应该使用显式强制转换gcc -pedantic认为应该,并且必须有充分的理由! :)我个人认为明确的演员阵容更清楚。如果可能的话,我也认为代码应该在没有警告的情况下进行编译,所以如果它是我的代码,我会添加显式转换。

<强>参考

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

2 Id。,sec。 7.18.1.4

3 Id。,sec。 6.3

4 Id。,sec。 3.4.1,将“实现定义的行为”定义为“未指定的行为,其中每个实现记录了如何做出选择”。这意味着转换是合法的,但结果在一个平台上可能与另一个平台上的结果不同。