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

时间:2021-05-17 21:42:36

I can't seem to make sense of a GCC compiler warning I get when I try to assign a void * value to a intptr_t variable. Specifically, when I compile with -std=c99 -pedantic, I get the following warning regarding the initialization of variable z on line 7:

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

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

警告:初始化从指针生成整数而没有强制转换[-Wint-conversion]

Here is the source code:

这是源代码:

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

Naturally, if I explicitly cast y to intptr_t then the warning disappears. However, I confused why the warning is present for implicit conversions when the whole purpose of intptr_t is in the conversion and manipulation of void * values.

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

From section 7.18.1.4 of the C99 standard:

从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:

以下类型指定一个带符号的整数类型,其属性是任何有效的void指针都可以转换为此类型,然后转换回指向void的指针,结果将比较原始指针:

intptr_t

Am I misinterpreting the standard, or is GCC simply overly pedantic in its "integer from pointer" check in this case?

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

1 个解决方案

#1


3  

Summing up! Apologies in advance for any errors — please leave me a comment.

加起来!如有任何错误,请提前道歉 - 请给我留言。

In C99:

  • Any pointer can be converted to an integer type.1
  • 任何指针都可以转换为整数类型

  • You might want to do that, e.g., if you are implementing your own operating system!
  • 您可能希望这样做,例如,如果您要实现自己的操作系统!

  • Conversions between pointers and integers can go horribly wrong,1 so are usually not what you want.
  • 指针和整数之间的转换可能会出现严重错误,1因此通常不是您想要的。

  • Therefore, the compiler warns you when you convert pointers to integers without casting. This is not overly pedantic, but to save you from undefined behaviour.
  • 因此,当您将指针转换为整数而不进行强制转换时,编译器会发出警告。这不是过于迂腐,而是为了避免未定义的行为。

  • intptr_t (and uintptr_t, and likewise throughout) is just an integer type,2 so it is subject to the same risks as any other pointer-to-integer conversion. Therefore, you get the same warning.
  • intptr_t(和uintptr_t,以及整个过程)只是一个整数类型,2因此它与任何其他指针到整数转换具有相同的风险。因此,您会收到相同的警告。

  • However, with intptr_t, you at least know that the conversion from a pointer won't truncate any bits. So those are the types to use — with explicit casts — if you really need the integer values of pointers.

    但是,使用intptr_t,您至少知道指针的转换不会截断任何位。所以这些是要使用的类型 - 使用显式强制转换 - 如果你真的需要指针的整数值。

    • The spec1, #6 says that

      spec1,#6说明了这一点

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

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

      With intptr_t, the result can be represented in the integer type. Therefore, the behaviour is not undefined, but merely implementation-defined. That is (as far as I know) why those types are safe to use for receiving values from pointers.

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

Edit

Reference 1, below, is part of section 6.3, "Conversions." The spec says:3

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

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

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

and refers to section 6.5.4 for a discussion of explicit casts. Therefore, the discussion in Reference 1 indeed covers implicit casts from any pointer type to intptr_t. By my reading, then, an implicit cast from void * to intptr_t is legal, and has an implementation-defined result.1, 4

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

Regarding whether the explicit cast should be used, gcc -pedantic thinks it should, and there must be a good reason! :) I personally agree that the explicit cast is more clear. I am also of the school of thought that code should compile without warnings if at all possible, so I would add the explicit cast if it were my code.

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

References

1C99 draft (since I don't have a copy of the final spec), sec. 6.3.2.3 #5 and #6).

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

2Id., sec. 7.18.1.4

2Id。,sec。 7.18.1.4

3Id., sec. 6.3

3Id。,sec。 6.3

4Id., sec. 3.4.1, defines "implementation-defined behavior" as "unspecified behavior where each implementation documents how the choice is made." The implication is that the conversion is legal, but that the result may be different on one platform than on another.

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

#1


3  

Summing up! Apologies in advance for any errors — please leave me a comment.

加起来!如有任何错误,请提前道歉 - 请给我留言。

In C99:

  • Any pointer can be converted to an integer type.1
  • 任何指针都可以转换为整数类型

  • You might want to do that, e.g., if you are implementing your own operating system!
  • 您可能希望这样做,例如,如果您要实现自己的操作系统!

  • Conversions between pointers and integers can go horribly wrong,1 so are usually not what you want.
  • 指针和整数之间的转换可能会出现严重错误,1因此通常不是您想要的。

  • Therefore, the compiler warns you when you convert pointers to integers without casting. This is not overly pedantic, but to save you from undefined behaviour.
  • 因此,当您将指针转换为整数而不进行强制转换时,编译器会发出警告。这不是过于迂腐,而是为了避免未定义的行为。

  • intptr_t (and uintptr_t, and likewise throughout) is just an integer type,2 so it is subject to the same risks as any other pointer-to-integer conversion. Therefore, you get the same warning.
  • intptr_t(和uintptr_t,以及整个过程)只是一个整数类型,2因此它与任何其他指针到整数转换具有相同的风险。因此,您会收到相同的警告。

  • However, with intptr_t, you at least know that the conversion from a pointer won't truncate any bits. So those are the types to use — with explicit casts — if you really need the integer values of pointers.

    但是,使用intptr_t,您至少知道指针的转换不会截断任何位。所以这些是要使用的类型 - 使用显式强制转换 - 如果你真的需要指针的整数值。

    • The spec1, #6 says that

      spec1,#6说明了这一点

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

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

      With intptr_t, the result can be represented in the integer type. Therefore, the behaviour is not undefined, but merely implementation-defined. That is (as far as I know) why those types are safe to use for receiving values from pointers.

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

Edit

Reference 1, below, is part of section 6.3, "Conversions." The spec says:3

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

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

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

and refers to section 6.5.4 for a discussion of explicit casts. Therefore, the discussion in Reference 1 indeed covers implicit casts from any pointer type to intptr_t. By my reading, then, an implicit cast from void * to intptr_t is legal, and has an implementation-defined result.1, 4

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

Regarding whether the explicit cast should be used, gcc -pedantic thinks it should, and there must be a good reason! :) I personally agree that the explicit cast is more clear. I am also of the school of thought that code should compile without warnings if at all possible, so I would add the explicit cast if it were my code.

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

References

1C99 draft (since I don't have a copy of the final spec), sec. 6.3.2.3 #5 and #6).

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

2Id., sec. 7.18.1.4

2Id。,sec。 7.18.1.4

3Id., sec. 6.3

3Id。,sec。 6.3

4Id., sec. 3.4.1, defines "implementation-defined behavior" as "unspecified behavior where each implementation documents how the choice is made." The implication is that the conversion is legal, but that the result may be different on one platform than on another.

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