Re: When to use const modifier?



santosh wrote:
Ian Collins wrote:
Leonardo Korndorfer wrote:
I'm litle confused by the const modifier, particularly when use const

Are string literals "real constants", whatever that means? I thought you
were just supposed to pretend that they were constants, and treat them
as such, to prevent the wrath of UB.


Here, C's subtle goals for portability surface. Some memory pages are marked read-only. Any attempted write to a read-only page by a user mode program [contrasted with supervisor mode running the OS's kernel] will result in an interrupt raised by the Memory Management Unit [MMU], the part of the CPU that translates virtual addresses to physical addresses. This interrupt notifies the kernel your program is behaving badly. The default behavior in this case is an abrupt termination known as a "core dump."

Executable files produced by modern linkers are partitioned into segments. The ".data" segment is expected to be read-only and *may* be mapped to a read-only page in virtual memory. Attempting to write it results in the above behavior. This is the meaning of "real constant": the hardware and OS will not permit you to write it after the loader brings that segment into memory and protects the page. String literals are typically placed in the ".data" segment, so treat them as "real constants."

This differs somewhat from use of the 'const' keyword. When const is used in a variable definition, the compiler typically attempts to infer its value. If the compiler can guess the initial value at compile time, and by definition the variable's value cannot change after initialization, then it may optimize the value away. That is, replace all instructions loading that variable with load-immediate instructions. If you attempt to take the address of that variable, or the compiler chooses not to get rid of it, it may place that value in the ".data" segment again resulting in a "real constant."

You may implicitly cast a non-const to const. Depending on how you structure your program, you may know that, by design, some function should not have reason to modify its data. You may declare that data const to express this fact. Because the compiler knows that nothing will attempt to modify the data when the particular function is called, all sorts of optimization trickery becomes possible. The function may be executed concurrently with others, an OpenMP compiler may spawn separate threads, VLIW compilers may issue multiple instructions with correct knowledge that no data dependencies exist, and so on.

Given a constant variable, you may cast away the const property and then write to it. This is only guaranteed to work if you are certain that the variable was defined as nonconst. The following example illustrates the difference between "real constant" and "not as constant as it seems."

void modify(const int *p_a) {
*((int *)p_a) = 7; // take life into own hands; hope caller
// knew what s/he was doing
}

int main() {
int a = 5;
const int b = 5;

modify(&a); // ok: passing the address of a non-const int

modify(&b); // bad: passing the address of a const int.
// Results undefined.

return 0;
}

The first call to modify() works because modify()'s body correctly assumes that it has really received a pointer to a non-const int. The second call is likely to fail because that assumption is incorrect.

The author of the modify() function is making some pretty bold assumptions about the caller and is lying about it in its parameter list. That's not advised.

Hope this clarifies things.

--
Andrew Kerr
.



Relevant Pages

  • Re: Separate compilation and access to small integer data in other programs
    ... reasons than `const', of course. ... if the header says `extern const int razzle;' but the definer says ... but the compiler most definitely will.) ... return privateRazzle; ...
    (comp.lang.c)
  • Re: Need some info on const char **
    ... I don't think the compiler will really like this (it could ... just says 'cast to pointer to const pointer of something ... right and tells me it's using 'int' as the default type. ... promises that foo will not change anything through ca. ...
    (comp.lang.c)
  • Re: Smart pointers of const objets
    ... >> object directly to a reference if it is the exact type of a sub type ... I've put some reasons below (including a const correctness violation). ... int main ... the most compliant compiler I have does create a temporary. ...
    (comp.lang.cpp)
  • Re: restrict in plain English?
    ... compiler might generate this code itself, ... Since the data may be const, the function presumably does not try to ... All it means that you cannot modify the data through this ... int f ...
    (comp.lang.c)
  • Re: where do the automatic variables go ?
    ... int main ... segment, what happens to these automatic variables? ... Stack variables are implied by the compiler (the compiler generates code ...
    (comp.os.linux.misc)