本文介绍了“来自整数的指针/来自不带强制转换的指针的整数"问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

限时删除!!

该问题旨在作为整数和指针问题之间所有初始化/分配的常见问题解答条目.

我想编写将指针设置为特定内存地址(例如0x12345678)的代码.但是,当使用gcc编译器编译此代码时,出现初始化使指针从整数开始而没有强制转换"的警告/错误:

I want to do write code where a pointer is set to a specific memory address, for example 0x12345678. But when compiling this code with the gcc compiler, I get "initialization makes pointer from integer without a cast" warnings/errors:

int* p = 0x12345678;

类似地,这段代码给出了初始化从指针进行整数转换而无需强制转换":

Similarly, this code gives "initialization makes integer from pointer without a cast":

int* p = ...;
int i =  p;

如果在变量声明行之外执行相同的操作,则消息相同,但显示赋值"而不是初始化":

If I do the same outside the line of variable declaration, the message is the same but says "assignment" instead of "initialization":

p = 0x12345678; // "assignment makes pointer from integer without a cast"
i = p;          // "assignment makes integer from pointer without a cast"

使用其他流行的编译器进行的测试还会给出错误/警告消息:

Tests with other popular compilers also give error/warning messages:

  • c语指针转换不兼容的整数"
  • icc说不能使用类型为int的值来初始化类型为int*的实体"
  • MSVC(cl)说:初始化int*的间接级别与int不同".
  • clang says "incompatible integer to pointer conversion"
  • icc says "a value of type int cannot be used to initialize an entity of type int*"
  • MSVC (cl) says "initializing int* differs in levels of indirection from int".

问题:以上示例是否有效?

以及后续问题:

这不会给出任何警告/错误:

This does not give any warnings/errors:

int* p = 0;

为什么不呢?

推荐答案

否,它不是有效的C,也从来没有有效的C.这些示例是所谓的标准的约束违反.

No, it is not valid C and have never been valid C. These examples are so-called constraint violation of the standard.

该标准不允许您初始化/将指针分配给整数,也不允许将整数分配给指针.您需要使用强制转换强制强制类型转换:

The standard does not allow you to initialize/assign a pointer to an integer, nor an integer to a pointer. You need to manually force a type conversion with a cast:

int* p = (int*) 0x1234;

int i = (int)p;

如果不使用强制转换,则代码无效C,并且不允许编译器在不显示消息的情况下让代码通过.具体来说,这受简单分配(C17 6.5.16.1§1:

If you don't use the cast, the code is not valid C and your compiler is not allowed to let the code pass without displaying a message. Specifically, this is regulated by the rules of simple assignment, C17 6.5.16.1 §1:

约束

应满足以下条件之一:

  • 左侧的操作数具有原子,限定或不限定的算术类型,右侧的操作数具有 算术类型
  • 左操作数具有结构或联合类型的原子,限定或非限定版本 与权利的类型兼容;
  • 左操作数具有原子,限定或不限定的指针类型,并且(考虑类型) 左值转换后,左操作数将具有)两个操作数都是限定值的指针 或兼容类型的非限定版本,并且左侧指向的类型具有所有 右边指出的类型的限定词;
  • 左操作数具有原子,限定或不限定的指针类型,并且(考虑类型) 左值转换后,左操作数将具有)一个操作数是指向对象类型的指针, 另一个是指向合格或不合格版本的void的指针,类型指向 左边有右边所指类型的所有限定词;
  • 左边的操作数是原子,合格或不合格的指针,右边的是空指针 持续的;或
  • 左边的操作数的类型是atomic,合格或不合格的_Bool,右边的是指针.
  • the left operand has atomic, qualified, or unqualified arithmetic type, and the right has arithmetic type;
  • the left operand has an atomic, qualified, or unqualified version of a structure or union type compatible with the type of the right;
  • the left operand has atomic, qualified, or unqualified pointer type, and (considering the type the left operand would have after lvalue conversion) both operands are pointers to qualified or unqualified versions of compatible types, and the type pointed to by the left has all the qualifiers of the type pointed to by the right;
  • the left operand has atomic, qualified, or unqualified pointer type, and (considering the type the left operand would have after lvalue conversion) one operand is a pointer to an object type, and the other is a pointer to a qualified or unqualified version of void, and the type pointed to by the left has all the qualifiers of the type pointed to by the right;
  • the left operand is an atomic, qualified, or unqualified pointer, and the right is a null pointer constant; or
  • the left operand has type atomic, qualified, or unqualified _Bool, and the right is a pointer.

对于int* p = 0x12345678;,左操作数是指针,右操作数是算术类型.
对于int i = p;,左操作数是算术类型,右操作数是指针.
这些都不符合上面提到的任何约束条件.

In case of int* p = 0x12345678;, the left operand is a pointer and the right is an arithmetic type.
In case of int i = p;, the left operand is an arithmetic type and the right is a pointer.
Neither of these fit in with any of the constraints cited above.

关于int* p = 0;起作用的原因,这是一个特例.左边的操作数是一个指针,右边的是 null指针常量. 有关空指针,空指针常量和NULL宏之间的区别的更多信息.

As for why int* p = 0; works, it is a special case. The left operand is a pointer and the right is a null pointer constant. More info about the difference between null pointers, null pointer constants and the NULL macro.

一些注意事项:

  • 如果将原始地址分配给指针,则该指针可能需要符合volatile的条件,因为它指向诸如硬件寄存器或EEPROM/闪存位置之类的东西,可以更改其内容在运行时.

  • If you assign a raw address to a pointer, the pointer likely need to be volatile qualified, given that it points at something like a hardware register or an EEPROM/Flash memory location, that can change its contents in run-time.

即使是强制转换,也不能保证将指针转换为整数.标准(如C17 6.3.2.3§5和§6所述):

Converting a pointer to an integer is by no means guaranteed to work even with the cast. The standard (C17 6.3.2.3 §5 and §6 says):

任何指针类型都可以转换为整数类型.除非事先指定,否则结果 是实现定义的.如果结果不能用整数类型表示,则行为是 不明确的.结果不必在任何整数类型的值范围内.

Any pointer type may be converted to an integer type. Except as previously specified, the result is implementation-defined. If the result cannot be represented in the integer type, the behavior is undefined. The result need not be in the range of values of any integer type.

说明性脚注:

此外,与大多数64位系统一样,指针的地址可能大于int内部的地址.因此,最好使用<stdint.h>

In addition, the address from a pointer might be larger than what will fit inside an int, as is the case for most 64 bit systems. Therefore it is better to use the uintptr_t from <stdint.h>

这篇关于“来自整数的指针/来自不带强制转换的指针的整数"问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

1403页,肝出来的..

09-06 15:32