Monday, August 13, 2007

Const and Volatile Qualifier

* Const
- Read only
- Initialization
const type must be initialized when it is declared.
     const int j; /* error */
- Specify the exact data type
     #define i 10
     const long j = 10;
     char h = i;
     char k = j; /* error due to truncation */
- Save memory
Memory is allocated once.
     #define STRING "abcdefg"
     const char string[] = "abcdefg";
     printf(STRING); /* first time allocation */
     printf(string);
     printf(STRING); /* second time allocation */
     printf(string);
- Change const
     const int i = 0;
     int *p = (int *)&i;
     *p = 10;

* Volatile
- Usage
-- Hardware registers or ports which might be changed by I/O
-- Non-automative variables in ISR which might be changed by ISR
-- Global variables in multi-threading environment which might be changed by other thread.
- Effect
Compiler would re-read this variable from the cache or memory instead of register.

* Qualifier Meaning
- int const/volatile *p = &i;
- int * const/volatile p = &i;
- int volatile * const p = &i;

* Declaration of Const and Volatile
- Two types of declaration
     const/volatile int i; <=> int const/volatile i;
The latter one might be better. Think about this one:
     typedef char * pchar;
     const pchar p;
It might be explained as "const char *" but actually it is "char * const". The declaration of "pchar const p" has no such confusion.
- Declaring an entire object to be volatile and/or const effectively
declares each member of that object as volatile and/or const.
- Defining a data type to be const and/or volatile might be more useful than just defining an object of this type to be const and/or volatile. The reason of this is no need to consider the type match (as explained below) when pointer assignments happen, like parameter passing in function calling. Otherwise, all these occurances should be declared as const and/or volatile.
Note: typedef struct A const AA; =>
AA is const but struct A is not. So use this format:
typedef struct A
{
...
} const B;

* Const/Volatile Pointer Assignment
     int *p = &i;
     int const *cp; /* No initialization is allowed since cp is a pointer not const pointer actually */
     p = cp; /* error */
     cp = p;
In the above example, cp is a pointer to a qualified data type while p is a pointer to a unqualified data type. In the assignment, the data type to which the left pointer points should be with the qualifier of the right one. So cp could not be assigned to p.
     int **pp = &p;
     int const **cpp;
     cpp = pp; /* error */
which might happen in the parameter passing of function calling. Why?
pp => a pointer to a pointer to int
cpp => a pointer to a pointer to const int
"A pointer to int" is not the same data type as "a pointer to const int". Therefore, pp and cpp is different pointers. Casting needed here. If
pp => a pointer to a pointer to int (int **)
cpp => a pointer to a const pointer to int (int * const *) or
           a const pointer to a const pointer to int (int * const * const) or
           a const pointer to a pointer to int (int ** const)
then cpp = pp; is legal.

No comments: