【发布时间】: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