在C中,const变量是否保证在内存中是不同的?

说到字符串文字,C99标准说(6.4.5.6):

如果这些数组的元素具有适当的值,则这些数组是否不同是未指定的。 如果程序试图修改此类数组,则行为未定义。

我找不到类似的警告或对const变量的明确保证。 可以在上下文中使用表达式&x == &y const int x=12; const int y=12; const int x=12; const int y=12; 评价为1 ? const变量和字符串文字怎么样(即使在32位little-endian平台上, &x == "\014\000\000"保证为0 )?

对于它的价值, 本博客文章中的 “字符串文字”部分给出了问题的背景。

在标准中,相等性在§6.5.9“等式运算符”中讨论,并在§6.5.3.2“地址和间接运算符”中讨论,而const在§6.7.3“类型限定符”中讨论。 关于指针平等的相关段落是§6.5.9.6:

两个指针比较相等,当且仅当两个都是空指针时,两者都是指向同一对象的指针(包括指向对象的指针和开头的子对象)或函数, [或超过数组末尾的指针]

&的唯一定义是“一元&运算符产生其操作数的地址。 […]结果是指向由其操作数指定的对象或函数的指针。“(§6.5.3.2.3)。 遗憾的是,“地址”一词没有正式定义; 但是不同的对象(对于由==定义的相等)具有不同的地址,因为地址是由上面的等式定义不同的指针。

至于const的含义,§6.7.3并不表示const对于什么构成一个对象有任何影响(它是“执行环境中的一个数据存储区域,其内容可以代表值”,§3.14 )。 脚注进一步表明“如果从未使用过地址,则实现不需要为这样的对象分配存储”。 虽然这是非规范性的,但强烈表明如果使用地址,则必须为每个对象分配存储。

请注意,如果对象是const volatile ,那么它很明显(就像volatile一样清晰)它们不能具有相同的地址,因为const volatile对象是可变的。 (§6.7.3.10有一个使用const volatile的例子。)

即使在非易失性情况下, const只表示程序的这一部分不允许修改对象,而不是通常对象是只读的。 要将const对象的存储与其他东西合并,大胆的实现者必须保证没有任何东西可以修改对象。 对于具有单独编译的实现中具有外部链接的对象而言,这是相当困难的(但当然,我们正在远离标准并进入未实践的领域)。

如果这是关于编写C程序,那么您可以通过为对象提供不同的值来增加机会:

 const int x = __LINE__; const int y = __LINE__; 

如果这是关于C的理论模型,我会选择使对象区别开来。 您必须通过在论文(扩展版本)的段落中总结答案来certificate这一选择的合理性。

另一方面,如果这是关于编写优化编译器,我怀疑它会伤害许多真实世界的程序来合并常量。 我想在嵌入式编译器中进行合并,用户习惯于使用边缘情况安全地播放它,并且节省的内存可以是不可忽略的。 我反对在托管平台上合并,任何收益都可以忽略不计。

(参考N1256又名C99 + TC3。我不认为版本有所不同。)

据我所知,标准不允许任何类型的两个命名对象具有相同的地址(联盟成员除外)。 从6.5.9 / 6:

两个指针比较相等,当且仅当两个指针都是空指针时,两个指针都是指向同一个对象的指针…

字符串文字不是const变量,所以你的第二个问题没有实际意义,我不知道32位和字节序有什么关系。

 const int x=12; const int y=12; 

xy是不同的变量(都是const限定的),因此具有不同的地址。

对于另一个例子也是如此。

请注意, const是对象的限定符。 关于内存布局,如果它存在与否则没有区别。

6.4.5 / 6说明了与字符串文字对应的数组:

如果这些数组的元素具有适当的值,则这些数组是否不同是不明确的。

这是一个允许折叠字符串文字的特定规则。 我不知道标准中对于其他对象说同样的事情。