Output difference in gcc and turbo C
Why is there a difference in the output produced when the code is compiled using the two compilers gcc
and turbo c
.
#include <stdio.h>
int main()
{
char *p = "I am a string";
char *q = "I am a string";
if(p==q)
{开发者_如何学JAVA
printf("Optimized");
}
else{
printf("Change your compiler");
}
return 0;
}
I get "Optimized"
on gcc
and "Change your compiler"
on turbo c
. Why?
Your questions has been tagged C as well as C++. So I'd answer for both the languages.
[C]
From ISO C99 (Section 6.4.5/6
)
It is unspecified whether these arrays are distinct provided their elements have the appropriate values.
That means it is unspecified
whether p
and q
are pointing to the same string literal or not. In case of gcc
they both are pointing to "I am a string"
(gcc optimizes your code) whereas in turbo c
they are not.
Unspecified Behavior: Use of an unspecified value, or other behavior where this International Standard provides two or more possibilities and imposes no further requirements on which is chosen in any instance
[C++]
From ISO C++-98 (Section 2.13.4/2
)
Whether all string literals are distinct(that is, are stored in non overlapping objects) is implementation defined.
In C++ your code invokes Implementation defined behaviour.
Implementation-defined Behavior:
Unspecified Behavior where each implementation documents
how the choice is made
Also see this question.
Since your string literal is a constant expression, i.e. you should not modify it via a pointer, there is no real purpose in storing it in the memory space twice. Being a newer compiler, gcc merges the literals by default while Turbo C does not. It is a sign of gcc's support for the newer language standard that has the notion of const data.
Please forget the answers in the same line as
"It's because Turbo C is SO TOTALLY OLD and they couldn't do it THEN, because it had to be FAST, but the GCC is totally NEW and RAD and that's why it does that!".
Both compiler support merging string constants as an option. The GCC option (-fmerge-constants
) is turned on at optimization levels, while the Turbo C Option (-d
) is turned off on default. If you are using the TCC IDE, then go to Options|Compiler...|Code Generation..
and check "Duplicate strings merged
".
From the gcc manual page :
-fmerge-constants
Attempt to merge identical constants (string constants and floating point constants) across compilation units.
This option is the default for optimized compilation if the assembler and linker support it. Use -fno-merge-constants to inhibit this behavior.
Enabled at levels -O, -O2, -O3, -Os.
Hence the output.
Turbo C was optimized for fast compilation, so it doesn't have any features that would slow it down. Recognizing duplicate strings would be a slow-down, even if only minor.
The compiler may keep two copies of identical literals if it thinks proper. Finding out if that is the case is presumably the point of this program.
In the good old days, assemblers kept all literals in a literal pool, and patching the literal pool was a recognised (if not approved) technique of modifying 'constants' throughout the program.
If by some chance the compiler allows in this case *p = 'H';
then important differences in behaviour would result.
Historical footnote: Since addresses were smaller than floating-point numeric constants, FORTRAN used to handle floating-point constants much like C handles strings. Since memory was precious, identical constants would be allocated the same space. Also, parameter passing was always done by reference. This meant that if one passed a numeric constant to a procedure that modified its argument, other occurrences of that "constant" would change value.
Hence the old saying: "Variables won't; constants aren't."
Incidentally, has anyone noticed the bug in the Turbo C 2.0 printf which would fail when using a format like "%1.1f" to print numbers like 99.99 (outputs 00.0)? Fixed in 2.01, it reminds me of the Windows 3.1 calculator bug.
精彩评论