Where does a const
variable gets stored exactly and how does it behaviour change? Say for example:
const int i=10; // stores where ?
main()
The compiler determines if the address of the constant is ever needed. If it is not, it is (usually) input inline into the code segment because that's (usually) faster than referencing memory.
If the address is needed, then the constant is stored as if it were a non-const variable in the current scope (relatively depending upon compiler). That is, global consts generally get stored in your data segment, function (parameter or declared) consts generally get stored on the stack.
Think of it like a register variable. It's in your CPU's register, if you're familiar with that. It's in your CPU's register until you need its address. Then it's put into addressable space.
The real question is initialization - if you need its address and is therefore actually allocated, then where is it initialized? There's something for you to ponder.
Per the C standard (n1256 draft):
6.7.3 Type qualifiers
...
3 The properties associated with qualified types are meaningful only for expressions that are lvalues.114)
...
5 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.115)
...
114) The implementation may place aconst
object that is notvolatile
in a read-only region of storage. Moreover, the implementation need not allocate storage for such an object if its address is never used.
115) This applies to those objects that behave as if they were defined with qualified types, even if they are never actually defined as objects in the program (such as an object at a memory-mapped input/output address).
In short, a const
-qualified object may be stored in a different area from non-const
-qualified objects, but not necessarily.
The const
qualifier is an instruction to the compiler to reject code that attempts to modify that object directly; attempts to modify the object indirectly (as you do in the second code snippet) results in undefined behavior, meaning any result is possible.
Modifying your code to print the value:
#include <stdio.h>
main()
{
const int j=20;
int *p;
p=&j;
(*p)++;
printf("%d\n", j);
return 0 ;
}
The above code, when compiled with gcc 4.3.2 at -O1
optimisation or above, results in the output 20
rather than 21
. This shows that it hasn't really "worked" - it just appeared to work.
A const
qualifier isn't a request to have the variable placed in a particular kind of memory - it's a promise from you to the compiler, that you won't modify that variable by any means. The compiler can rely on your promise to optimise the code that's produced - and if you break your promise, it won't necessarily break in an obvious way, it may just produce strange results.
When you declare (non-extern, non-argument) and initialize variable as const
, this means variable is not writable at all. So compiler is free to place it to read only section. Though it may be modifiable physically (if hardware allows it). Or not modifiable, if it protected by MMU or placed in ROM in standalone application.
Standard does not state, what should happen if you try to write const (it is called "undefined behaviour"), so anything may happen: it may be written, not written, cause exception, hang, or something else you cannot imagine. C not so paranoid as, say, Ada, and all unxepected behaviour is up to programmer, not compiler or RTL.
As many stated it is inlined in most cases (if compiler know that to inline), but still retains attributes of variables, such as address (and you can get a pointer), size. If all const reads and pointers to it are eliminated, storage for const will also be eliminated by compiler (if it is static or local) or linker (if it is global).
Note, local pointers may also be eliminated if their locations can be computed in compile time. Also writes to local variables may be eliminated if they're not read after it, so your snippet may have no code at all.
Automatic local variable may be compiled in static storage if compiler prove that only one instance of it is needed. As const is not modifiable it also compiled in static storage, but may be eliminated as stated above.
In all your examples all consts may firstly be put static storage (const section) and then easily eliminated.
I don't know where it is stored, because that's implementation-defined, but your code results in undefined behaviour.
Its totally up to the compiler writer what happens to the const, and it will vary according to the optimisation you request.
In your first example the constants are never used so the compiler probably will just ignore them altogether.
In your second example as you use "address off" it must actualy store it somewhere -- probably at the begining of the stack.
As C is designed to replace assembly language instructions, and for writing OS kernal and device driver type code it lets you do all sorts of things and assumes you know what you are doing when you start messing with pointers.