Reputation: 61
#include<stdio.h>
int main()
{
const int a=1;
int *p=(int *)&a;
(*p)++;
printf("%d %d\n",*p,a);
if(a==1)
printf("No\n");//"No" in g++.
else
printf("Yes\n");//"Yes" in gcc.
return 0;
}
The above code gives No
as output in g++
compilation and Yes
in gcc
compilation. Can anybody please explain the reason behind this?
Upvotes: 3
Views: 1295
Reputation: 2334
Okay we have here 'identical' code passed to "the same" compiler but once with a C flag and the other time with a C++ flag. As far as any reasonable user is concerned nothing has changed. The code should be interpreted identically by the compiler because nothing significant has happened.
Actually, that's not true. While I would be hard pressed to point to it in a standard but the precise interpretation of 'const' has slight differences between C and C++. In C it's very much an add-on, the 'const' flag says that this normal variable 'a' should not be written to by the code round here. But there is a possibility that it will be written to elsewhere. With C++ the emphasis is much more to the immutable constant concept and the compiler knows that this constant is more akin to an 'enum' that a normal variable.
So I expect this slight difference means that slightly different parse trees are generated which eventually leads to different assembler.
This sort of thing is actually fairly common, code that's in the C/C++ subset does not always compile to exactly the same assembler even with 'the same' compiler. It tends to be caused by other language features meaning that there are some things you can't prove about the code right now in one of the languages but it's okay in the other.
Usually C is the performance winner (as was re-discovered by the Linux kernel devs) because it's a simpler language but in this example, C++ would probably turn out faster (unless the C dev switches to a macro or enum and catches the unreasonable act of taking the address of an immutable constant).
Upvotes: 1
Reputation: 227400
Your code triggers undefined behaviour because you are modifying a const
object (a
). It doesn't have to produce any particular result, not even on the same platform, with the same compiler.
Although the exact mechanism for this behaviour isn't specified, you may be able to figure out what is happening in your particular case by examining the assembly produced by the code (you can see that by using the -S
flag.) Note that compilers are allowed to make aggressive optimizations by assuming code with well defined behaviour. For instance, a
could simply be replaced by 1
wherever it is used.
Upvotes: 10
Reputation: 134326
In your code, notice following two lines
const int a=1; // a is of type constant int
int *p=(int *)&a; // p is of type int *
you are putting the address of a const int
variable to an int *
and then trying to modify the value, which should have been treated as const
. This is not allowed and invokes undefined behaviour.
For your reference, as mentioned in chapter 6.7.3, C11
standard, paragraph 6
If an attempt is made to modify an object defined with a
const
-qualified type through use of an lvalue with non-const
-qualified type, the behavior is undefined. If an attempt is made to refer to an object defined with a volatile-qualified type through use of an lvalue with non-volatile-qualified type, the behavior is undefined
So, to cut the long story short, you cannot rely on the outputs for comaprison. They are the result of undefined behaviour.
Upvotes: 4
Reputation: 310980
From the C++ Standard (1.9 Program execution)
4 Certain other operations are described in this International Standard as undefined (for example, the effect of attempting to modify a const object). [ Note: This International Standard imposes no requirements on the behavior of programs that contain undefined behavior. —end note ]
Thus your program has undefined behaviour.
Upvotes: 6