【问题标题】:About reinterpret_cast and pointer关于 reinterpret_cast 和指针
【发布时间】:2018-09-18 09:19:55
【问题描述】:

我正在学习 C 和 C++。 在这个程序中:

#include <iostream>

int main() {

    const int g = 10;
    int * k = reinterpret_cast <int *> (20000); //ok
    std::cout << "k : " << k  << std::endl;
    std::cout << "* k : " << * k << std::endl;

    * k = g;
    std::cout << "* k : " << *k << std::endl;

    return 0;
}

./converForTyEn
k : 0x4e20 分段错误(核心转储)

我预计是 20000,然后是 10。但似乎错误是“意味着您试图访问您无权访问的内存”。 (埃尔西·芬恩)。 感谢您的帮助。

【问题讨论】:

  • k指向内存地址20000,你的程序不允许访问这个地址,因此运行时停止它。
  • 好的,谢谢你的解释。
  • 不要将 C 与 C++ 混淆,它们是两种不同的语言。我不太了解 C,但是除了极少数例外,您的代码不是有效的 C(例如 return 0; 您也可以用 C 编写;)

标签: c++ pointers casting


【解决方案1】:

该标准的工作草案 (N4713) 规定了有关使用

8.5.1.10 重新解释演员表
...
5. 整数类型或枚举类型的值可以显式转换为指针。转换为足够大小的整数(如果实现中存在这样的整数)并返回相同指针类型的指针将具有其原始值;指针和整数之间的映射是由实现定义的。 [ 笔记: 除 6.6.4.4.3 中所述外,此类转换的结果不会是安全派生的指针值。 ——尾注]

还有:

6.6.4.4.3 安全派生指针 [basic.stc.dynamic.safety]
...
2. 指针值是指向动态对象的安全派生指针,前提是它具有对象指针类型并且是以下之一
(2.1) — 调用 ::operator new(std::size_t) 或 ::operator new(std::size_t, std::align_val_t) 的 C++ 标准库实现返回的值;
(2.2) — 获取由通过安全派生指针值间接产生的左值指定的对象(或其子对象之一)的地址的结果;
(2.3) — 使用安全派生的指针值的定义明确的指针算术的结果;
(2.4) — 安全派生的指针值的明确定义的指针转换的结果;
(2.5) — 安全派生指针值的 reinterpret_cast 的结果;
(2.6) — 安全派生指针值的整数表示的 reinterpret_cast 的结果;

(2.7) — 一个对象的值,其值是从一个可跟踪的指针对象复制而来的,在复制时,源对象包含一个安全派生的指针值的副本。

由于您在整数文字 (20000) 上使用 reinterpret_cast,因此转换的结果不是安全派生的指针值。尝试取消引用此类指针值会导致未定义的行为。

【讨论】:

  • int g = 10; int * k = reinterpret_cast > (&g); std::cout k : "
  • 在这种情况下,&amp;g 是一个安全派生的指针。请参阅上述答案中的 2.2。
  • 我是计算机科学的新手,也是 C++ 的新手。 C++ 编程语言标准工作草案共 1448 页。这个草稿怎么用?
  • C++ 最新工作草案将在线提供。实际标准的购买成本很高。但是草稿已经足够接近实际使用了。这是一个链接:google.co.in/…
  • 我认为我必须使用工作草案和书籍来理解和编写正确的 C++ 程序。
【解决方案2】:

指针必须指向要使用的有效内存。在您的情况下,您将其设置为任意内存位置 20000。

一个有效指针用法的例子是

int x = 42;
int *px = &x;

这会将x 的地址放入px

std::cout << px;

会输出地址。

std::cout << *px;

会输出x的值。

【讨论】:

  • 事实上,制作无效指针本身就是UB。如果一个指针是空指针,如果它指向某个东西,或者如果它指向数组末尾之后的一个元素,则该指针是有效的。
  • reinterpret_cast &lt;int *&gt; (20000); = UB
【解决方案3】:

您的代码调用未定义行为 (UB),可能的输出是:

k : 0x4e20
Segmentation fault

其中第一行是k 的地址。然后,在这行代码中:

std::cout << "* k : " << * k << std::endl;

您正在尝试访问该地址,该地址不在您的程序段内,从而导致分段错误。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-06-05
    • 2021-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-13
    • 2021-09-09
    相关资源
    最近更新 更多