2013-01-21 40 views
12

C语言中的以下代码是否具有已定义的行为?从const指针中删除const是否遵守C中的严格别名,并引用同一个对象?

int main() { 
    const int i = 0; 
    return *(int*)(&i); 
} 

我问,因为6.5/7列出为一个有效的别名“与有效对象的类型兼容的类型的合格版本”。但对象的有效类型是const int,我不认为intconst int的合格版本(尽管情况正好相反)。 intconst int兼容(6.7.3/10)。

此外,6.3.2.3/2表示可以通过将指针类型转换为限定符,并且生成的指针是相等的。 6.3.2.3/7说你可以转换任何两种指针类型(所以铸造(int*)(&i)本身是允许的)。但并不是说所产生的指针指向的是同一个对象,或者说它是平等的。它所说的是它可以转换回原来的类型(在这种情况下为const int*)。也就是说,即使别名是合法的,我也不清楚标准是否保证了我的指针转换确实会产生一个指向i的指针。

那么,标准实际上是否定义了我的代码的行为,如果是这样定义的呢?

我知道代码在实践中的作品。我想到了一个假想的(和奇怪的)实现,它不起作用。我可以问这个实现是否符合标准(如果没有,它违反了什么部分),但是如果我的想象实现不符合其他方面,我不想浑水。如果有人认为它会帮助他们回答这个问题,我会描述实施情况。

+0

对于转换回int const *标准清楚地表明结果必须是标识。 “否则,当再次转换时,结果应与原始指针相等。” –

+0

@JensGustedt:同意。这对我的代码没有帮助,因为我的代码永远不会将它转换回'int const *'。 –

回答

7

它是由§6.7.3P5至少暗示它的工作原理,:

如果试图通过使用左值的修改与 常量限定类型定义的对象使用非const限定的 类型时,行为是未定义的。如果试图通过使用非易失性限定类型的左值 来引用通过易失性限定类型定义的对象 ,则行为是未定义的。

注意,对于volatile限定类型,它说,但对于const限定的类型,它只是说修改,这意味着非修改的访问是OK(“来证明例外规则“)。

虽然在我看来,您可能已经发现了标准中的缺陷。

+0

我也认为这应该是一个缺陷,但另一方面,这意味着我们知道const变量是如何实现的。 – Spidey

+1

我不同意:虽然常量限定没有通过未定义的类型化表达式进行非修改访问,但有效的键入规则仍然这样做:不同的限定类型不兼容(除了通过参数确定函数类型的兼容性)和规则只是放宽*额外*资格的方向 – Christoph

+2

@Christoph:我同意这是严格阅读别名规则的结果,但我的观点是我不认为这是*意图*效果,因为它会使我所引用的规范性段落完全没有实际意义,也不能解释为什么不同的措词被用于常量和不稳定的情况。 – caf

相关问题