The original post is missing on my server, so I am replying to
a followup.
int main(void)
{
const int num = 100;
int *ip;
ip = (int *)#
*ip = 200;
The effect at this point is officially undefined by the C standard,
so *anything* *could* happen. What likely *does* happen is just
what is shown below:
printf("value of num is %d(%d) \n", num, *ip);
}
In article <3F************ ***@france-paris.org>
Jean-Michel Collard <jm@france-paris.org> writes:It seems to be compiler dependent and even changes with optimisations.
[without optimization]value of num is 200(200)
[with optimization]value of num is 100(200)
This is highly expect-able. :-)
First, remember that the "const" keyword in C is peculiarly named,
like so many C keywords: "struct" means "define a type"; "typedef"
means "do NOT define a new type"; "static" has nothing to do with
electricity :-) ; and "const" means "read-only".
Thus:
const int num = 100;
means: "Allocate a plain old ordinary variable that could change
like any plain old ordinary variable, but please Mr Compiler, if
you are able and willing, please put it into memory that is in fact
read-only. Oh and by the way I also promise never, ever to change
this variable -- you may count on me sir, I never make misteaks!" (sic)
Now, as it happens, gcc is not able or willing to place this variable
in read-only memory (because gcc assumes there is a conventional
stack, and puts all its automatic variables on that stack, and does
not try to protect any sub-parts of it against writing). If you
compile without optimization, gcc also forgets about your promise
not to change the variable.
On the other hand, if you turn on optimization, gcc remembers your
promise. You promised the variable "num" would always be 100 --
so the printf() call can substitute in the promised value for the
first %d.
The pointer "ip", of course, points to the actual variable (which
the compiler did not place in read-only memory after all) that
was initially 100. You achieved this by using a cast to tell the
compiler: "Hey Mr Compiler, I am smarter than you: this pointer
value from &num, that has type `pointer to read-only int', really
points to a read/write int. So even though this assignment is
suspicious and dodgy and you would normally tell me I am doing
something foolish, I invoke the All-Powerful-Cast syntax to shut
you up!" And -- because gcc was unwilling or unable to put "num"
in really, truly read-only memory, this, too, is actually correct.
The variable "num" *is* an ordinary int variable when gcc is done
compiling, because -- despite your asking gcc to please put it in
read-only memory -- it went into read/write memory.
Then, when you said "*ip = 200;" you told the compiler to change
the value of the memory from its original 100 to the new 200.
The compiler no doubt generated code to do this, and since "num"
was -- despite your request -- in read/write memory, the assignment
changed it.
Thus, you broke your promise never to change "num".
You lied to the compiler. It got its revenge, by producing different
code under optimization (where it assumed you kept your promise)
than without optimization (where it did not).
Note that it requires a pointer cast to achieve this lie. Avoid
pointer casts and you will avoid many mistakes. This is part of
the reason comp.lang.c wisdom says "do not cast malloc()".
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it
http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.