为什么使用两个编译器
gcc
和turbo c
编译代码时产生的输出存在差异。
#include <stdio.h>
int main()
{
char *p = "I am a string";
char *q = "I am a string";
if(p==q)
{
printf("Optimized");
}
else{
printf("Change your compiler");
}
return 0;
}
我在
"Optimized"
上得到 gcc
,在 "Change your compiler"
上得到 turbo c
。为什么?
您的问题已被标记为 C 和 C++。所以我会回答两种语言。
[C]
来自 ISO C99 (
Section 6.4.5/6
)
It is unspecified whether these arrays are distinct provided their elements have the appropriate values.
这意味着
unspecified
和p
是否指向相同的字符串文字。在 q
的情况下,它们都指向 gcc
(gcc 优化您的代码),而在 "I am a string"
中,它们不是。未指定的行为: 使用未指定的值或本国际标准规定的其他行为 两种或多种可能性,并且对任何选择中的选择不施加进一步的要求 实例
turbo c
来自 ISO C++-98 (
[C++]
)
Section 2.13.4/2
在 C++ 中,您的代码调用实现定义的行为。 实现定义的行为: 未指定的行为,其中每个实现
Whether all string literals are distinct(that is, are stored in non overlapping objects) is implementation defined.
如何做出选择
这个问题。
“这是因为 Turbo C 太老了,他们当时无法做到这一点,因为它必须很快,但 GCC 是全新且 RAD 的,这就是它这样做的原因!”。
两个编译器都支持合并字符串常量作为选项。 GCC 选项 (
documents
) 在优化级别打开,而 Turbo C 选项 (
-fmerge-constants
) 在默认情况下关闭。如果您使用的是 TCC IDE,请转到 -d
并选中“Options|Compiler...|Code Generation..
”。-fmerge-常量
尝试合并相同的常量(字符串常量和 浮点常数) 编译单位。
如果汇编器是优化编译的默认选项 和链接器支持它。使用 -fno-merge-constants 来抑制这种行为。
在 -O、-O2、-O3、-Os 级别启用。
因此输出。
在过去的美好时光,汇编器将所有文字保存在文字池中,并且修补文字池是一种公认的(如果没有批准的话)修改整个程序中“常量”的技术。
如果编译器偶然允许这种情况
Duplicate strings merged
,那么将会导致行为上的重要差异。
因此有句老话:“变量不会;常量则不会。”
顺便说一句,有没有人注意到 Turbo C 2.0 printf 中的错误,当使用“%1.1f”这样的格式打印 99.99(输出 00.0)这样的数字时,该错误会失败? 2.01 已修复,这让我想起了 Windows 3.1 计算器的 bug。