string跨翻译单位的文字地址

我想问问是否可移植性依赖跨翻译单位的string文字地址? 即:

一个给定的文件foo.c引用了一个string文字"I'm a literal!" ,它是正确的和可移植的依赖在其他给定的文件, bar.c在实例, 相同的string文字 "I'm a literal!" 会有相同的内存地址 ? 考虑到每个文件将被翻译成个人.o文件。

为了更好地说明,请遵循一个示例代码:

 # File foo.c /* ... */ const char * x = "I'm a literal!" # File bar.c /* ... */ const char * y = "I'm a literal!" # File test.c /* ... */ extern const char * x; extern const char * y; assert (x == y); //Is this assertion going to fail? 

和一个gcc示例命令行:

 gcc -c -o foo.o -Wall foo.c gcc -c -o bar.o -Wall bar.c gcc -c -o test.o -Wall test.c gcc -o test foo.o bar.o test.o 

在同一翻译单位呢? 如果string文字在同一个翻译单元中,这是否可靠?

你不能依靠相同的string文字具有相同的内存位置,这是一个实现的决定。 C99草案标准告诉我们,没有指定相同的string是否是不同的,从6.4.5 string文字

没有说明这些数组是否是不同的,只要它们的元素具有适当的值。 如果程序试图修改这样一个数组,行为是不确定的。

对于标准草案第2.14.5节中涉及的C ++, string文字说:

是否所有string文字都是不同的(即,是否存储在不重叠的对象中)是实现定义的。 尝试修改string文字的效果是未定义的。

编译器允许汇集string文字,但是你必须理解它是如何从编译器到编译器的,所以这不是可移植的,可能会改变。 Visual Studio包含一个string文字池的选项

在某些情况下,可能会汇集相同的string文字以节省可执行文件中的空间。 在string文字池中,编译器会使对特定string文字的所有引用指向内存中的相同位置,而不是将每个引用点指向string文字的单独实例。 要启用string池,请使用/ GF编译器选项。

请注意,它确实符合在某些情况下

gcc确实支持合并和跨编译单元,你可以通过-fmerge-constants打开它:

尝试在编译单元之间合并相同的常量(string常量和浮点常量)。

如果汇编器和链接器支持,则此选项是优化编译的默认选项。 使用-fno-merge-constants来禁止这种行为。

注意,使用的尝试如果…支持它

至less对于C语言来说,由于不需要将string文字集中在一起,我们可以从这个关于string文字的comp.std.c文档的讨论中看出,其原因是由于当时的各种实现:

海湾合作委员会可能是一个例子,但不是动力。 部分在ROMmable数据中有string文字的愿望是支持,呃ROMROM。 我依稀记得使用了几个C实现(在X3J11做出决定之前),其中string文字被自动合并或存储在常量数据程序部分。 考虑到现有的各种实践以及在想要使用原始UNIX属性时可以轻松解决的问题,似乎最好不要保证string文本的唯一性和可写性。

,你不能指望相同的地址。 如果发生,发生。 但是没有什么可以执行。

§2.14.5 / p12

是否所有string文字都是不同的(即,是否存储在不重叠的对象中)是实现定义的。 尝试修改string文字的效果是未定义的。

编译器可以随心所欲。 如果它们处于不同的翻译单元中,或者即使它们处于相同的翻译单元中,也可以将它们存储在不同的地址中,而不pipe它们是只读存储器。

例如,在MSVC上,这两种情况下的地址是完全不同的,但是又一次:没有任何东西阻止编译器合并指针的值(即使只读区段约束被强制执行也不会)。