Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deep Analysis of Const Qualifier in C

Tags:

c

constants

Where does a const variable gets stored exactly and how does it behaviour change? Say for example:

const int i=10; // stores where ?  
main()  
{  
   const int j=20; //stores where?   
   return 0;  
}  

If the answer is Code segment then how does the following code work??

main()  
{  
   const int j=20;  
   int *p;  
   p=&j;  
   (*p)++;   
   return 0 ;  
} 

This code works fine... How it is possible to change a read only memory? How does it really get stored? Please explain it to me in detail.

like image 613
jack Avatar asked Nov 25 '10 09:11

jack


People also ask

What is const qualifier in C?

In general, the const qualifier is used to declare a variable as constant, meaning its value cannot change once the variable has been initialized.

What is the const qualifier explain with examples?

The const qualifier explicitly declares a data object as something that cannot be changed. Its value is set at initialization. You cannot use const data objects in expressions requiring a modifiable lvalue. For example, a const data object cannot appear on the lefthand side of an assignment statement.

Why do we require const qualifier in C?

We use the const qualifier to declare a variable as constant. That means that we cannot change the value once the variable has been initialized. Using const has a very big benefit. For example, if you have a constant value of the value of PI, you wouldn't like any part of the program to modify that value.

Where are constant qualifiers used?

The const keyword can be used as a qualifier when declaring objects, types, or member functions. When qualifying an object, using const means that the object cannot be the target of an assignment, and you cannot call any of its non-const member functions.


3 Answers

The keyword const indicates a variable that is read-only (i.e., cannot be changed at run-time). It does not indicate a compile-time constant. Therefore, all of the usual attributes of variables apply; specifically, it is allocated addressable storage space.

Unlike with #define, your constant is not necessarily inlined by the compiler. Rather, the compiler will create a symbol corresponding to your const declaration in the object file so that it can be accessed from other code files—remember that const objects have external linkage by default in C (although some compilers will still inline the constant value within the file where it is defined).

The reason the code snippet that you posted "works" is because the unary operator & can be applied to any lvalue, which includes a const object. Though the behavior here is undefined, I suspect that your compiler is detecting this usage and ensuring that your const declaration is given address space, and therefore not inlining it, even within the file it is declared.

EDIT: Also see: http://publications.gbdirect.co.uk/c_book/chapter8/const_and_volatile.html

Let's look at what is meant when const is used. It's really quite simple: const means that something is not modifiable, so a data object that is declared with const as a part of its type specification must not be assigned to in any way during the run of a program. It is very likely that the definition of the object will contain an initializer (otherwise, since you can't assign to it, how would it ever get a value?), but this is not always the case. For example, if you were accessing a hardware port at a fixed memory address and promised only to read from it, then it would be declared to be const but not initialized.

Taking the address of a data object of a type which isn't const and putting it into a pointer to the const-qualified version of the same type is both safe and explicitly permitted; you will be able to use the pointer to inspect the object, but not modify it. Putting the address of a const type into a pointer to the unqualified type is much more dangerous and consequently prohibited (although you can get around this by using a cast). For example...

like image 179
Cody Gray Avatar answered Oct 25 '22 04:10

Cody Gray


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.

like image 20
caf Avatar answered Oct 25 '22 04:10

caf


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 a const object that is not volatile 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.

like image 38
John Bode Avatar answered Oct 25 '22 05:10

John Bode