[blog] Tip: C variables and pointers declarations and definitions

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.)

Autor: Antonio Giacomelli de Oliveira

Engenheiro Eletrônico

Deixe uma Resposta

Preencha os seus detalhes abaixo ou clique num ícone para iniciar sessão:

Logótipo da WordPress.com

Está a comentar usando a sua conta WordPress.com Terminar Sessão /  Alterar )

Google photo

Está a comentar usando a sua conta Google Terminar Sessão /  Alterar )

Imagem do Twitter

Está a comentar usando a sua conta Twitter Terminar Sessão /  Alterar )

Facebook photo

Está a comentar usando a sua conta Facebook Terminar Sessão /  Alterar )

Connecting to %s