2016-10-13 44 views
2

我似乎无法理解GCC编译器的警告,当我尝试将void *值分配给intptr_t变量时,我会得到警告。具体地,当我与-std=c99 -pedantic编译,我得到关于可变z的第7行的初始化以下警告:是否将void *值设置为intptr_t变量需要显式强制转换?

警告:初始化将指针整数,未作施放[-Wint转换]

这里是源代码:

#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; 
} 

当然,如果我明确投yintptr_t则警告消失。然而,当intptr_t的整个目的是在void *值的转换和处理中时,我混淆了为什么会出现隐式转换的警告。

从部分C99标准的7.18.1.4

以下类型表示与属性有符号整数类型,任何有效 指针空隙可以转化为这种类型,那么转换回指针空隙, ,其结果将比较等于原始指针:

使用intptr_t

上午我误解的标准,或者是GCC只是在其“从指针整数”过于迂腐在这种情况下检查?

+0

这是[上一个问题](http://stackoverflow.com/questions/9492798/using-intptr- t-instead-of-void)有关吗? –

+3

这不是过于迂腐,隐式转换只是警告存在的常见错误来源,请考虑在涉及重载解决方案时它会如何变成疼痛。知道你在做什么,通过做一个(希望是C++风格的)转换来告诉编译器 – StoryTeller

+1

intptr_t是一个普通的整数类型,唯一的保证是它可以保存一个void *的所有相关信息,它是对于其他整数类型不能保证,所以警告是正确的。为什么你想在第一个地方使用整数?通常一个用于低级算术或位操作RESS。然后强烈建议'uintptr_t'。否则,想想三次(!)如果你真的想要一个整数持有一个指针。 – Olaf

回答

3

总结!对于任何错误提前道歉—请给我留言。

在C99:

  • 任何指针可以被转换为整数类型。
  • 你可能想这样做,例如,指针和整数之间if you are implementing your own operating system!
  • 转换可以去可怕的错误,等都是通常不是你想要的。
  • 因此,当您将指针转换为整数而不进行转换时,编译器会发出警告。这不是过于迂腐,而是为了避免不确定的行为。
  • intptr_t(和uintptr_t,以及全文)只是一个整数类型,因此它受到与任何其他指针到整数转换相同的风险。因此,你会得到同样的警告。
  • 但是,与intptr_t,你至少知道指针的转换不会截断任何位。所以这些是—使用类型明确转换—如果你真的需要指针的整数值。

    • 该规范1,#6

      ...的 结果是实现定义的。如果结果不能用整数类型表示,则 的行为未定义。

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

编辑

参考文献1,下面,是第6.3节的一部分, “转化”。细则中指出:

一些运营商自动转换操作数值从一种类型到另一个。这 节规定从这样的隐式转换所需要的结果......

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

关于是否明确投应该使用,gcc -pedantic认为它应该,并且必须有一个很好的理由! :)我个人同意明确演员更清楚。我也认为代码应该在没有任何警告的情况下编译,如果可能的话,所以如果它是我的代码,我会添加明确的转换。

参考

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

Id。,秒。 7.18.1.4

Id。,秒。 6.3

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

+0

我现在从第6.3.2.3节的第5和第6段中看到,整数和指针之间转换(因此intptr_t和void *')之间存在固有的风险。如果说从'void *'到'intptr_t'到'void *'的转换没有风险*未定义的行为*(如第6节所述)是否正确,因为'intptr_t'被定义为能够表示结果'void *'转换? –

+0

只是为了澄清:隐式转换对'void *'有效'intptr_t'(虽然有一个实现定义的结果),但通常建议使用显式类型转换来使代码的意图清晰。那是对的吗? –

+0

@VilhelmGray编辑 – cxw

相关问题