2011-06-04 27 views
11

说到字符串文字,C99的标准说(6.4.5.6):在C中,常量变量是否保证在内存中不同?

它是未指定的这些阵列是否是不同的条件是它们的元素具有适当的值。如果程序试图修改这样一个数组,那么行为是不确定的。

我找不到类似的警告或明确保证const变量。上下文const int x=12; const int y=12;中的表达式&x == &y能否计算为1?什么是const变量和字符串文字(即即使在32位小端平台上,&x == "\014\000\000"保证为0)?

对于它的价值,this blog post中的“字符串文字”部分给出了问题的上下文。

+0

注意,GCC将只能发出'x'和'y'如果可以采取的地址,并在这种情况下,它会在不同的地址发出它们。 – ninjalj 2011-06-04 13:10:59

+2

另请参阅:[C语言中的Const限定符深度分析](http://stackoverflow.com/questions/4275504/deep-analysis-of-const-qualifier-in-c) – 2011-06-04 14:12:46

回答

5

在标准中,平等在§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的有关理论模型,我会去制作对象不同。您必须通过在您的论文(扩展版)中的段落中总结答案来证明这一选择是合理的。另一方面,如果这是关于编写优化编译器的问题,我怀疑这会伤害许多真实世界的程序来合并常量。我会在嵌入式编译器中进行合并,用户习惯于在边缘情况下安全地播放它,并且保存的内存可能不可忽略。我会反对在托管平台上合并,任何收益都可以忽略不计。

(从N1256又名C99 + TC3引用。我不认为版本有差别。)

+0

当然,如果您要实施不合规的优化,即使在嵌入式目标上,也应该使其关闭。在这种情况下,假设在任何地方都有需求,那么您可以为任何/所有目标提供它,并留给用户决定是否会打破他们的计划,以及他们是否需要节省空间。 – 2011-06-04 14:02:07

+0

我喜欢你的论点,但关于非易失性常量段落“Even ......”,'GCC'编译'const int x = 12; int y; main() { y = x; f(); y + = x; printf(“%d \ n”,y); (假设'f()'不会改变常量变量'x'(它假设'f()'可能会改变'y'''), , – 2011-06-04 14:36:05

+0

@Pascal:对于这个测试是可靠的,你需要说服gcc使用'x'的地址,也就是说''x'在某些地方不会被优化掉。说服gcc它不知道'f'是否可以看到'x';在另一个文件中定义'extern'和'f'应该这样做 – Gilles 2011-06-04 14:41:51

6

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

两个指针比较,如果相同且仅当是空指针,都是 指向同一个对象 ...

字符串常量不是常量变量所以你的第二个问题是没有意义的,我不明白32位和字节序与它有什么关系。

+0

好的,提出第二个关于' const char [4] = {'a','b','c'};'和'“abc”'如果您愿意。 – 2011-06-04 12:50:53

+2

它们与它有什么关系是'x'(一个整数12)的对象表示恰好发生在一个32位小端平台上,以包含与字符串文字''\ 014 \'的对象表示相同的字节' 000 \ 000" '。所以我相信问题的一部分是,字符串文字可以折叠成“x”,还是字符串文字只能折叠成其他字符串文字。 – 2011-06-04 12:53:22

+0

@Steve哦,我明白了。谢谢。 @帕斯卡尔据我所知,标准只是说字符串文字的值可能不明确。但提供否定的证据很难。 – 2011-06-04 12:57:51

3

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

xy是不同的变量(两个常量限定)并且因此具有不同的地址。

其他示例相同。

请注意const是一个对象的限定符。关于内存布局,如果存在或不存在则没有区别。

1

6.4.5/6说对应于字符串文字阵列的:

它是unspeci音响ED这些阵列 是否是不同的提供它们的元素 具有适当的值。

这是一个允许折叠字符串文字的特定规则。我不知道标准中的任何内容对其他对象都是如此。