在 C 中,const 变量是否保证在内存中不同?
说到字符串文字,C99 标准规定 (6.4.5.6):
如果这些数组的元素具有适当的值,则未指定这些数组是否不同。如果程序尝试修改此类数组,则行为未定义。
我找不到类似的警告或对 const 变量的明确保证。表达式&x == &y
可以在上下文const int x=12; 中使用吗? const int y=12;
计算结果为 1
?那么 const 变量和字符串文字(即 &x == "\014\000\000"
保证为 0
即使在 32 位小-字节序平台)?
就其价值而言, 这篇博文给出了问题的背景。
Speaking of string literals, the C99 standard says (6.4.5.6):
It is unspecified whether these arrays are distinct provided their elements have the appropriate values. If the program attempts to modify such an array, the behavior is undefined.
I couldn't find either a similar warning or an explicit guarantee for const variables. Can the expression &x == &y
in the context const int x=12; const int y=12;
evaluate to 1
? What about a const variable and a string literal (i.e. is &x == "\014\000\000"
guaranteed to be 0
even on a 32-bit little-endian platform)?
For what it's worth, the section "String literals" in this blog post gives the context of the question.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
据我所知,标准不允许任何类型的两个命名对象具有相同的地址(联合成员除外)。从 6.5.9/6 开始:
字符串文字不是 const 变量,因此您的第二个问题没有实际意义,而且我不明白 32 位和字节序与它有什么关系。
As far as I'm aware, the Standard does not allow two named objects of any type to have the same address (except for union members). From 6.5.9/6:
String literals are not const variables so your secondary question is moot, and I don't see what 32-bitness and endianness have to do with it.
在该标准中,相等性在第 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 程序,那么您可以通过为对象赋予不同的值来增加机会:
如果这是关于 C 的理论模型,我会努力使对象不同。您必须通过在论文(扩展版本)的一个段落中总结答案来证明此选择的合理性。
另一方面,如果这是关于编写一个优化编译器,我怀疑合并常量会伤害许多现实世界的程序。我会选择合并到嵌入式编译器中,用户习惯于在边缘情况下保持安全,并且节省的内存可能是不可忽略的。我反对合并到托管平台中,因为任何收益都可以忽略不计。
(参考文献来自 N1256 又名 C99+TC3。我不认为版本有所不同。)
In the standard, equality is discussed in §6.5.9 “Equality operators”,
&
is discussed in §6.5.3.2 “Address and indirection operators”, andconst
is discussed in §6.7.3 “Type qualifiers”. The relevant passage about pointer equality is §6.5.9.6:The only definition of
&
is that “The unary&
operator yields the address of its operand. […] The result is a pointer to the object or function designated by its operand.” (§6.5.3.2.3). There is unfortunately no formal definition of the word “address”; but distinct objects (for the equality defined by==
) have distinct addresses, because the addresses are pointers that are distinct by the definition of equality above.As for the meaning of
const
, §6.7.3 doesn't indicate thatconst
has any bearing on what makes an object (which is “a region of data storage in the execution environment, the contents of which can represent values” by §3.14). A footnote further indicates that “the implementation need not allocate storage for such an object if its address is never used”. Although this is non-normative, it is a strong indication that if the address is used then storage must be allocated for each object.Note that if the objects are
const volatile
, then it is fairly clear (as clear asvolatile
can ever be) that they can't have the same address, becauseconst volatile
objects are mutable by the implementation. (§6.7.3.10 has an example of use ofconst volatile
.)Even in the non-volatile case,
const
only indicates that this part of the program is not allowed to modify the object, not that the object is read-only in general. To merge the storage of aconst
object with something else, the audacious implementer would have to guarantee that nothing can modify the object. This is fairly difficult for an object with external linkage in an implementation with separate compilation (but of course we're getting away from the standard and into the won't-happen-in-practice territory).If this is about writing a C program, then you can increase your chances by giving the objects different values:
If this is about a theoretical model of C, I'd go for making the objects distinct. You'll have to justify this choice by summarizing the answers here in a paragraph in (the extended version of) your paper.
On the other hand, if this is about writing an optimizing compiler, I doubt it would hurt many real-world programs to merge constants. I'd go for merging in an embedded compiler, where users are used to playing it safe with edge cases and where the memory saved could be non-negligible. I'd go against merging in a hosted platform where any gain would be negligible.
(References from N1256 a.k.a. C99+TC3. I don't think the version makes a difference.)
x
和y
中是不同的变量(均为 const 限定),因此具有不同的地址。
另一个例子也是如此。
请注意,
const
是对象的限定符。关于内存布局,有或没有都没有区别。In
x
andy
are different variables (both const-qualified) and therefore have different addresses.The same for the other example.
Note that
const
is a qualifier for an object. Regarding memory layout, it makes no difference if it's there or not.6.4.5/6 描述了与字符串文字对应的数组:
这是允许折叠字符串文字的特定规则。我不知道标准中是否有任何内容对其他对象说了同样的事情。
6.4.5/6 says of the arrays corresponding to string literals:
So that's a specific rule allowing string literals to be folded. I don't know of anything in the standard that says the same thing for other objects.