I wanted to know how the following works @ compiler level.
int const iVal = 5;
(int&)iVal = 10;
A bit of m/c or compiler level answer would be great full.
Thanks in advance.
I wanted to know how the following works @ compiler level.
int const iVal = 5;
(int&)iVal = 10;
A bit of m/c or compiler level answer would be great full.
Thanks in advance.
Why not run it through your cown ompiler and look at the assember output?
It is undefined behavior.
In the first line you define a constant integer. Henceforth, in your program, the compiler is permitted to just substitute iVal with the value 5. It may load it from memory instead, but probably won't, because that would bring no benefit.
The second line writes to the memory location that your compiler tells you contains the number 5. However, this is not guaranteed to have any effect, as you've already told the compiler that the value won't change.
For example, the following will define an array of 5 elements, and print an undefined value (or it can do anything it wants! it's undefined)
int const iVal = 5;
(int&)iVal = 10;
char arr[iVal];
cout << iVal;
The generated assembly might look something like:
sub ESP, 9 ; allocate mem for arr and iVal. hardcoded 5+sizeof(int) bytes
; (iVal isn't _required_ to have space allocated to it)
mov $iVal, 10 ; the compiler might do this, assuming that you know what
; you're doing. But then again, it might not.
push $cout
push 5
call $operator_ltlt__ostream_int
add ESP, 9
C-style cast acts as a const_cast. Like if you've written
const_cast<int&>( iVal ) = 10;
If you happen to do so and the compiler decides not to allocate actual memory for iVal, you run into undefined behaviour.
For example, VC7 compiles it allright. It even runs it allright in Debug mode. In Release mode iVal value doesn't change after the assignment – it remains 5.
So you should not do so ever.
This is possible because the idea of "const-ness" only exists in the language/compiler. In actual computer memory, everything is variable. Once the code has been compiled, your iVal
variable is simply a location in RAM.
edit: the above assumes that the constant is actually placed in memory. See sharptooth's answer.
Using the c-style cast tells the compiler to treat this memory location as if it were a simple integer variable, and set that value to 10.
Undefined behavior.
In release builds, most compilers will substitute the const value directly - but you could run into one that does a memory load. Also, the second assignment might or might not generate an access violation, depending on platform and compiler. Iirc Intel's compiler puts const data in read-only memory, and would thus generate an access violation at runtime.
If this were an embedded system, it's likely that iVal would be stored in flash, so writing to it would have no effect.
However, it is possible that the compiler would not regard this an error, as embedded compilers generally don't keep track of whether a particular area of memory is readable or not.
I suspect that it might pass the linker too, as a linker will typically determine that iVal is a constant, so goes in flash - but it's not the linker's job to determine how iVal is used.
Incidentally, this question is tagged with "C", but the "(int&)" syntax is not (AFAIK) valid C. The same could, however, be achived with something like:
int *Ptr = (int *) &iVal;
*Ptr = 10;