【问题标题】:Why is it possible to cast integer types to pointers?为什么可以将整数类型转换为指针?
【发布时间】:2015-06-28 01:55:29
【问题描述】:

所以,一个 void 指针是一个通用指针,它可以在以后指向任何字符或整数,对吧?但它是一个指针。但是,这编译没有任何错误:

void* ptr; 
long var;
ptr = (void*)var;

为什么可以在这里将long 类型转换为指针?它不应该给出错误吗?请注意,如果var 是int 或char,这也有效。

此外,如果 var 是 long,则以下 sn-p 有效!

cout<<(long)ptr;

但是,如果 var 是 int 或 char,这将不起作用。我不知道该怎么做。我使用的是 64 位 Linux 机器。

【问题讨论】:

  • 它不适用于 64 位平台。看我的回答。

标签: c++ pointers void void-pointers


【解决方案1】:

它有效,因为指针实际上是内存地址,而这些地址又由无符号整数(地址)表示。

注意,long 通常为 4 字节长,因此如果您切换到 64 位平台(其中指针为 64 位/8 字节长),它将无法保存内存地址。在这种情况下,将指针转换为int/long 将截断(从而使其无效)其内容。

要存储地址值,请使用uintptr_t(或签名版本,intptr_t),如here 所述:

intptr_t, uintptr_t

整数类型,能够保存从 void 指针转换而来的值,然后再转换回该类型,其值与原始指针的比较值相等。

可选:这些类型定义可能未在某些库实现中定义。*

这些类型是可选的,但在大多数实现中都可用。即使它们不存在,也应该为存储内存地址定义特定于平台的类型。

哦,你关于转换的观点不太正确——每个整数(有符号或无符号)值都可以通过显式转换转换为指针(任何类型,包括void*)。反之亦然。

【讨论】:

  • intptr_t 在&lt;stdint.h&gt; 中是标准的
  • @BasileStarynkevitch 1. 从技术上讲,C++ 中没有像&lt;stdint.h&gt; 这样的东西(它是&lt;cstdint&gt;,在我的答案中已链接)。 2. &lt;cstdint&gt; 是 C++ 11 的一项功能。 3. Documentation page for <cstdint> says, that both these types are optional.
  • 我的错误。我以为 OP 说的是 C,而不是 C++
  • 不,long 在大多数 POSIX 系统上为 8 字节长 en.wikipedia.org/wiki/64-bit_computing#64-bit_data_models
  • @LưuVĩnhPhúc 仔细阅读。我写通常 - MS Windows 使用LLP64 数据模型,它将long 定义为4 字节长。由于 MS 系统在桌面上的使用份额约为 90%,这就是 通常对我来说意味着什么。
【解决方案2】:

因为指针是对内存位置的数字引用,因此可以转换为数值。在许多情况下,它们之间的转换大致相同。例如,如果我有一个像 0x3E103A08 这样的 32 位内存位置(指针通常以十六进制形式查看),则该十六进制表示将是一个无符号整数,相当于 1041250824。更详细地说,32 位指针只有 4 个字节,32 位无符号整数也是如此。事实上,在 CPU 级别,使用了 CPU 寄存器——一些类似于指针,一些用于计算——所有这些(在我过去在 ASM 中开发)都更像是引擎盖下的整数变量。

【讨论】:

  • 这个问题没有提到或说明“成员指针” - 只有void*s 指向非成员变量,但你的基本观点是正确的:内存地址只是数字,如果你让编译器假设一个整数变量中有一个地址,或者将一个地址移入一个地址,它为什么要第二次猜测你?
  • 抱歉,我正在写其他东西。我根本不是会员的意思。 ;)(错字)
  • 关于 hex/dec 的部分很奇怪。是同一个号码。你的帖子听起来像十六进制是指针,十进制是int。 (不,指针一般不以十六进制形式查看。)
  • 这是因为大多数时候指针是以十六进制形式查看的,而不是整数。
【解决方案3】:

由于指针包含地址,而地址是(类似整数的)数字,您可以这样做,
就像您可以将int 转换为long 或long 转换为int。显式转换告诉编译器你知道潜在的问题,所以它不会给你警告。

但是,完全不能保证 long 可以像指针一样保存相同的值范围,
所以不要使用long 作为地址。

【讨论】:

  • 如果您想保证long var 可以保持与void * 相同的值范围,请改用size_t var
  • @portforwardpodcast 你是说intptr_t/uintptr_t吗?
  • @portforwardpodcast No. long 和 size_t 和 void* 是三个不同的东西。
  • 好的@MohitJain 我想我误解了。这篇文章为我清除了它stackoverflow.com/questions/1464174/size-t-vs-intptr-t
  • 这就是这个网站的美妙之处,许多困惑被清除,忘记的东西可以被记住。
猜你喜欢
  • 1970-01-01
  • 2014-08-15
  • 1970-01-01
  • 2022-07-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-06
相关资源
最近更新 更多