It might sound naive, but it is a very common interview question, and I actually think the notation can be deceiving. And furthermore, it is essential. A few months off and you will be asking yourself “how is that again?”. Unless you get this rule: start reading from right to left.
Question: Please read the following declarations and explain their properties regarding read and write.
#1 int v;
Reads as v is a variable of integer type
int v; //declaration int same_scope_var = 0x10; //declaration and definition v = 0; //definition v = same_scope_var; //redefinition v=0x10
After the scope (declaration) and initial value of v is defined, you can read and write it in run-time.
#2 int const v;
Reads as v is a constant integer, i.e., read-only
After the scope and initial value of v is defined, you can only read it in run-time.
#3 int *v;
Reads as v is variable pointer to an integer.
int *v; //declaration int same_scope_var = 0xFFFFFFFF; //declaration and defitinion int same_scope_var2 = 0xF0FFFFFF; //declaration and defitinion v = &same_scope_var ; //definition v = &same_scope_var2 ; //definition
After the scope and initial value (that is a memory address that holds an integer) of v is defined, you can change it to whatever other integer address you want in run-time.
#4 int const *v;
Reads as v is variable pointer to a constant integer; that is, the address v holds can change, although it is expected to point to a constant value.
int const same_scope_k = 0xFFFFFFFF; //declaration and defitinion int const same_scope_k2 = 0xF0FFFFFF; int same_scope_var = 0xF0FBFFFF; int const *v; //declaration v = &same_scope_k; //definition v = &same_scope_k2; //redefinition *v = same_scope_k; //error wont compile v = &same_scope_var; //probably compile with a warning
After the scope and initial value of v is defined, you can write and read it whenever you want in run-time, but you cannot change the value it points to by dereferencing.
#5 int * const v;
Reads as v is a constant pointer to a variable integer, i.e., v is ready-only, but the value that it points to (dereference) can change.
int same_scope_variable = 0xFFFFFFFF; //declaration and definition int same_scope_variable2 = 0xF0FFFFFF; int * const v; //declaration v = &same_scope_variable ; //definition *v = same_scope_variable2; // redefinition for same_scope_variable = same_scope_variable2
After the scope and initial value of v is defined, you can only read the address it points to in run-time, but you can change the value the pointed address holds, by dereferencing.
#6 int const * const v;
Reads as v is a constant pointer to a constant integer. That is, the value v holds is a read-only address that points to a read-only integer. Its more usual to see that as a function argument when you want to be sure the method cannot change neither the address v holds nor the value it dereferences.
int const same_scope_k = 0xFFFFFFFF; int const same_scope_k2 = 0xF0FFFFFF; int const * const v; //declaration v = &same_scope_k; //defined, read-only v = &same_scope_k2; //error wont compile *v = same_scope_k2; //error wont compile
The code below should compile with no warnings. It is on a PC, therefore memory addresses have 8 bytes
#include <stdio.h> int main() { int my_variable = 0x30; int const my_constant = 0x60; //#1 defined and declared v int v = 0x05; //#2 defined and declared read-only const int const v_k = 0x10; int const v_k2 = 0x11; //#3 defined and declared v_ptr as the address of v int *v_ptr = &v; //#4 declared and defined this as a pointer to a constant int const *v_ptr_to_k = &v_k; //#5 declared and defined this as a constant pointer to an variable integer int * const v_k_ptr = &my_variable; //#6 //declared and defined this as a constant pointer to a constant integer int const * const v_k_ptr_k = &my_constant; // operations // change v printf("v has the value %x, and v_ptr is %p\n\r", *v_ptr, v_ptr); v = 0x80; printf("v has now the value %x, and v_ptr is %p\n\r", *v_ptr, v_ptr); // changing v_ptr v_ptr = &my_variable; printf("v_ptr dereferences to value %x, and v_ptr is %p\n\r", *v_ptr, v_ptr); //change pointer to a constant printf("v_ptr_to_k dereferences to value %x, and v_ptr_to_k is %p\n\r", *v_ptr_to_k, (unsigned long int *)v_ptr_to_k); v_ptr_to_k = &v_k2; printf("v_ptr_to_k dereferences to value %x, and v_ptr_to_k is %p\n\r", *v_ptr_to_k, (unsigned long int *)v_ptr_to_k); //*v_ptr_to_k = 0x08; //<== not allowed! //operating with a constant pointer printf("v_k_ptr dereferences to the value %x, and v_k_ptr is %p\n\r", *v_k_ptr, (unsigned long int *)v_k_ptr); v = 0x35; *v_k_ptr = v; printf("v_k_ptr dereferences to the value %x, and v_k_ptr is %p\n\r", *v_k_ptr, (unsigned long int *)v_k_ptr); //operating with a constant pointer to a constant integer printf("v_k_ptr_k dereferences to the value %x, and v_k_ptr_k is %p\n\r", *v_k_ptr_k, (unsigned long int *)v_k_ptr_k); //*v_k_ptr_k = 0x92; <== not allowed! //v_k_ptr_k = &my_constant; <== not allowed! return 0; }
Output:

(Erratum: in the printf above v_ptr_to_k was mentioned as v_ptr_k but the variable declared and defined on the code is v_ptr_to_k.)