【问题标题】:Pointer to integer and back again指向整数的指针并再次返回
【发布时间】:2016-04-21 12:58:28
【问题描述】:

首先,让我强调一下,这个问题本质上是合法。我询问以下程序在实践中是否可以在实际实现中工作,我询问的是根据 ISO 最严格的法律解释它是否合法(:= 不产生未定义的行为) -9899 标准(:1999 和 :2011)。

问题是是否允许将指针转换为uintptr_t 整数,对该整数执行一些算术运算,将其返回到相同的值,然后将整数转换回指针。

那么,下面的程序合法吗(在某种意义上它不会产生未定义的行为)?

#include <stdint.h>
#include <stdio.h>
int
main(void)
{
  int answer = 42;  void *ptr;
  uintptr_t deepthought;
  ptr = &answer;
  deepthought = (uintptr_t)ptr;
  ptr = 0;
  deepthought ^= 0xdeadbeef;
  printf("I'm thinking about it...\n");
  deepthought ^= 0xdeadbeef;
  ptr = (void *)deepthought;
  printf("The answer is: %d\n", *((int *)ptr));
  return 0;
}

再一次,我知道这段代码在任何实际系统上都不会造成任何困难。问题是它是否符合 C 标准中的法律术语,尤其是。 ISO-9899:1999 中的 §7.18.1.4 / ISO-9899:2011 中的 §7.20.1.4,其中短语“具有任何指向 void 的有效指针的属性的无符号整数类型都可以转换为此类型,然后转换回指向void的指针,结果将与原始指针比较”:不清楚“然后转换回”是否允许中间算术计算。

为了让这个问题不那么理论化,这里是人们可能希望禁止这种处理的一个原因。如果我们稍微改变一下这个例子,让指针是mallocated 而不是指向一个局部变量,并且如果它碰巧在一个带有(保守的)垃圾收集器的实现上运行,那么可以想象内存可以被回收在printf 调用期间,因为在那一刻,没有任何东西指向该内存区域。因此,如果 C 标准使上述示例非法(例如,如果不能将任何内容写入一个一直没有合法指针值的指针),这为垃圾收集器所做的假设提供了合法的理由。

但我再说一遍,问题是关于 C 标准的解释学,而不是任何实际或现实世界的结果。

【问题讨论】:

    标签: c pointers language-lawyer c99


    【解决方案1】:

    是的,它必须有效。

    根据我阅读标准语言的方式,您可以将 deepthought 的值写入文件(例如使用 fwrite),销毁程序中该值的任何副本,然后再次从文件中读取该值(@ 987654323@)。如此读取并转换为指针的值必须与原始指针比较。我没有找到任何禁止这样做的措辞。

    可以移动对象地址的垃圾收集器必须考虑到这种可能性。

    【讨论】:

    • 垃圾收集在这种语义下基本上是不可能的,除非人们愿意永久泄漏任何地址可能已经暴露给外界的对象。
    猜你喜欢
    • 1970-01-01
    • 2013-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-30
    • 1970-01-01
    相关资源
    最近更新 更多