Weight and health related risks.


Try it and it's free. PC and mobile version can be found on my website Healthfirst.

 

C Pointers and arrays



What is the pointer?





Without too much theory
, the pointer is a variable that stores the memory address of another variable that is stored somewhere in the memory . The pointer is the most powerful tools in C language and its misuse can lead to undesirable results . The pointer itself has an address and that address is of type integer. I'll illustrate different situations through examples .

How to declare a pointer
?

Before going into the details
, I would like to emphasize the relationship between a standard declared variable and the memory . Let's see what does the following mean .

Int counter
= 10 ;

This declares a variable named counter of type integer and assign or initialize it to
10. The variable counter is stored somewhere in the memory and can be accessed by using its name which is counter. Note that the variable counter has an address in the memory and it's this address which will be used to access the counter variable value either directly by variable name or via a pointer which will store the memory address of this variable. This is true for any other type of variable such as char , double , float and so on . The question is : How the address of the variable is assigned to pointer . This is done as shown below .



Step1: Declare your variable


int counter ;

The counter variable has an address in the memory which is accessed by using the unary operator
& that precedes the variable name counter as follow & counter . The variable address ( memory address of the variable ) is assigned by the system . If for any reason , you wish to know this address then do the following :

printf
( "\nThe address of variable counter is % p" , & counter ); // Use the format specifier %p

This above statement displays the memory address where the variable counter is stored
. The storage address of the variable depends of the systems as well as the operating system and the compiler used . For example , the statement printf ( "\nThe address of variable counter is % p" , & counter ); will display something like : The address of variable counter is 33DC if you're using 16 bit system and something like : The address of variable counter is 012433DC if the system is 32 bit . Once again , the result could be different from system to another . The most important thing to retain in here is that on 16 bit systems , the address is displayed as 4 bytes hexadecimal such as 33DC and on the 32 bit systems the address is displayed as 8 bytes hexadecimal such as012433DC . For this tutorial , I assume the system is 32 bit .
Now
, let's assign a value to the variable counter . Suppose the address of the variable counter is 012433DC.
int counter = 10 ; //this means the value 10 of the variable counter is stored at the memory
address 012433DC.
To display the value of the variable counter that is stored at that address
, use a statement such as the one below .
printf
( "\nThe value of the variable counter is : % d" , counter ); Note the absence of & operator . To display the value of the variable counter use the format specifier % d .


Step2: Declare the pointer


Pointer general syntax


< data_type > *< pointer_name >;

Where
< data_type > is a valid C data type such as int , double , float , char
And
< pointer_name > is any string satisfying the naming convention C variable .
We stick to our example and we declare a pointer of type integer as follow:


int * ptrint ; //This declares a pointer to an integer. ptrint could be any other name

The operator * is called dereferencing operator .
Assign the address of the counter variable to the pointer ptrint
.
ptrint
= & counter ; // Note no asterisk before ptrint

Note1 : The pointer ptrint has its own address
Note2
: The pointer ptrint has a value which is the address of the variable counter which is 012433DC.


To display the address of the pointer ptrint use the statement
:
printf
( "The pointer ptrint address is : % p" , & ptrint ); //This will display something like: 0125ABBA

To display the value of the pointer ptrint which is the address of the variable counter use the statement : printf ( "\nThe pointer ptrint value is : % p" , ptrint ); //Note the format specifier %p used in the statement, because the value of the pointer ptrint is an address. The value of ptrint is the address of the variable counter which is 012433DC.

To display the value to which the pointer ptrint points , use the following statement :
printf
( "\nthe value pointed to by ptrint is : % d\n" , * ptrint ); //This displays the counter value which is 10. In order to get the value stored at the address of the variable counter you must use the dereferencing operator *.

To display the size of the pointer ptrint use the statement :
printf
( "\nThe size of the pointer ptrint is : % d bytes" , sizeof ( ptrint ));
This will display
4 bytes on 32 bit systems and 2 bytes on 16 bit systems .

I put the concepts all together in the program below
. I'll comment each line when it's necessary .

#include <stdio.h>
int main ()
{
int counter ; /*Declare a variable of data type integer*/
int * ptrint = NULL ; /*Declare the pointer ptrint that points to an integer and initialize it to
NULL. This avoid the pointer to not point mistakenly to any memory
block which in such case can lead to undesirable results. */


counter
= 25 ; /*assign 25 to counter */
ptrint
= & counter ; /*Assign the address of the counter to ptrint*/

        
/* To output the memory address of variable counter, write the following statement
           Note the use of the format specifier %p */

printf
( "\nThe address of variable counter is % p" , & counter );

/* To display the stored value of the variable counter, use the statement below */
printf
( "\nThe value of the variable counter is : % d" , counter );
/* Note the format specifier %d and the absence of & */

/*The following statement displays the address of the pointer ptrint
  Remember the pointer has its own address in the memory
  The result will be a 4 bytes on 32 bit systems and a 2 bytes on 16 bit systems*/

printf
( "The pointer ptrint address is : % p" , & ptrint );

/*The statement below outputs the value of the pointer ptrint
  Remember, the value of ptrint is an address which is in this case
  the address of the variable counetr. Therefore, the format
  specifier %p must be used. Note the absence of the unary operator &*/

printf
( "\nThe pointer ptrint value is : % p" , ptrint );

/*Since we already wrote ptrint = &counter, the above statement is equivalent to
printf("\nThe pointer ptrint value is: %p", &counter);*/


/*To display the value pointed to by the pointer ptrint, use the syntax below.
  This value is nothing else than the value stored at the address of the variable counter which is the value 25.
*/

printf
( "\nthe value pointed to by ptrint is : % d\n" , * ptrint );

/* To display the size of the pointer ptrint use the statement:*/
printf
( "\nThe size of the pointer ptrint is : % d bytes" , sizeof ( ptrint ));

/*This will display 4 bytes on 32 bit systems and 2 bytes on 16 bit systems. I'll elaborate on sizeof when I'll deal with the dynamic memory allocation later*/
/*The following changes the value 25 stored in counter variable to 100. The change is done via the pointer ptrint rather the variable counter itself.*/
* ptrint = 100 ; //This is equivalent to counter = 100;

return 0 ; //Hands control to operating system
}



Important Notes


1. * ptrint and counter both refer to the contents of the variable counter ( that is , whatever data value stored there ).
2. ptrint and & counter both refer to the address of the variable counter ( the ptrint only hold the address of variable counter not the actual data value ).
3. The following statements are equivalent ( same ). int * ptrint ; int * ptrint ; and int * ptrint ; the asterisk can be placed anywhere between the data type and the pointer name . Personally , I use the first one . Don't confuse * for the pointer with * for multiplication operation such as in counter * counter which calculate 100 times 100 = 10000.


Uninitialized pointers

Now I go one step back to our famous pointer ptrint . Suppose we have the following scenario :
int * ptrint
At this stage
, our pointer is declared but not initialized yet . Therefore , the pointer ptrint does not point to any known address .
What will happen
if somebody attempts ( to initialize ) to assign a value as in the following statement ?
* ptrint = 100 ;
This assigns the value
100 to the pointer ptrint , but at what address ???? Of course , the memory address to which the pointer points and could be anywhere in the memory . As the result of doing so , the value 100 may overwrite important data that is stored at that given memory address . The result can be anything from storage program errors to a full system crash . This is not what we want . To fix this issue , I suggest always initialize the pointers . How is this done ?
As you can see in the program above
, I used NULL to initialize the pointer .
The right thing to
do is :
int * ptrint = NULL ;
In the
case of the string , initialize the pointer as shown here :
char * name = "" ; //This initialize the pointer name to an empty string


Arithmetic operations on the pointers

The C pointers support the arithmetic operations . However , these operation differs from the standard arithmetic operation such the one used on the standard variable . The examples below illustrate this fact .


Example1: standard variable


int counter = 25 ;

The two statements below are equivalent and they produce the same result
. This is known as addition .

counter
= counter + 1 ; //Increment the counter by one to set it to 26
counter += 1 ; // Increment the counter by one to set it to 26
The two statements below are equivalent and they produce the same result . This is known as substraction .
counter
= counter - 1 ; //Decrement the counter by one to set it to 24
counter -= 1 ; //decrement the counter by one to set it to 24


Example2: Pointers






int counter = 30 ;
int * ptrint = NULL ;
ptrint
= & counter ;
What does the following mean
?
ptrint
++; ptrint += 1 ; ++* ptrint ; ++(* ptrint ); (* ptrint )++; (* ptrint ); ptrint =- 1 ; and so on .

ptrint
++ and ptrint += 1 and prtint = ptrint + 1 :
I assume the data type is integer
. The result could be different for other data type such as char , double , float . To know what is the size of these data type use sizeof ( data_type ) as in sizeof ( double ), sizeof ( float ) and so on .
The above three expressions are equivalent
. They increment the value of the pointer ptrint by 1. This value is the address of the variable counter to which the pointer points . The 1 is not the ordinary 1. Here 1 means block of bytes . If the system is 16 bits , then ptrint will be incremented with 2 bytes and if the system is 32 bits , then ptrint will be incremented by 4 bytes . The following example shows how this is done .
Let say the ptrint value is
1000. Then ptrint ++ = ptrint += 1 = ptrint = ptrint + 1 = 1002 on 16 bits system and 1004 on 32 bits system . So , if you were expecting the result to be 1001 then that's wrong .

*++ ptrint :
This means increment the pointer ptrint then use the value pointed to
.

(* ptrint )++:
This means use the value pointed to and increment it
, not the pointer .

* ptrint ++ which can be written as *( ptrint ++):
This means the pointer ptrint is not incremented until the pointed to value is dealt with
.

These expressions are shown in the program below
. The program is well commented .


#include <stdio.h>
int main ()
{
/*Declare an array of 7 integers and initialize it */
int count [ 7 ] = { 100 , 300 , 500 , 700 , 800 , 900 , 950 };
/*Declare the pointer ptr of integer type and intialize to NULL*/
int * ptr = NULL ;
int i ; /*Used in the for loop*/

/*The variables below used to show sizeof(data_type)*/
double var1 ;
float var2
;
char var3 ;
printf
( " - Show the use of sizeof ( data_type ) in bytes \n" );
printf
( "\nSize of var1 of type double is % d bytes" , sizeof ( double ));
printf
( "\nSize of var2 of type float is % d bytes" , sizeof ( float ));
printf
( "\nSize of var3 of type char is % d bytes\n" , sizeof ( char ));
printf
( "\n" );

/*Assign the address of the first element of array
  to the pointer ptr*/

 
ptr
= count ; /*this can be written as ptr = &count[0] */

/*Outputs the address of the pointer in decimal format*/
printf
( "\nThe pointer ptr memory address = % d" ,& ptr );

/*outputs the memory address of variable count. In this
case is the first element of array count. count[0]*/

printf
( "\nThe variable count memory address = % d" ,& count );

/*Outputs the value of pointer ptr which is the memory
  address of the variable count to which it points, this
  is same as the above*/

 
printf
( "\nThe pointer ptr value which is memory address of count = % d\n" , ptr );
/*This loop outputs the 4 first elements of the array count
  and their respective memory addresses */

for ( i = 0 ; i <= 3 ; i ++)
{
printf
( "\n * ptr ++ = count [% d ]= % d address of count< [% d ]= % d" , i ,* ptr , i , ptr );
* ptr ++; /* Don't increment the pointer untill the value it
points to is displayed*/

}

/* This display the last value of the loop for because the
pointer ptr is not incremented after that*/

printf
( "\n\n After the loop for " );
printf
( "\n * ptr ++ = count [% d ]= % d address of count [% d ]= % d" , i ,* ptr , i , ptr );
  
(* ptr )++; //This increment the value pointed to by ptr and not the address
printf ( "\n\n (* ptr )++ = % d I incremeted the above value by 1 ,* ptr );
ptr
+= 1 ; /* can be written as ptr++
This increment the address pointed to by the pointer ptr */

printf
( "\npointer ( ptr += 1 ) = ptr ++ = % d" , ptr );
return 0 ;
}

Program outputs

Show the use of sizeof ( data_type ) in bytes
Size of var1 of type
double is 8 bytes
Size of var2 of type
float is 4 bytes
Size of var3 of type
char is 1 bytes

The pointer ptr memory address
= 13528
The variable count memory address
= 13514

The pointer ptr value which is memory address of count
= 13514
* ptr ++ = count [ 0 ]= 100 address of count [ 0 ]= 13514
* ptr ++ = count [ 1 ]= 300 address of count [ 1 ]= 13516
* ptr ++ = count [ 2 ]= 500 address of count [ 2 ]= 13518
* ptr ++ = count [ 3 ]= 700 address of count [ 3 ]= 13520


After the loop
for
* ptr ++ = count [ 4 ]= 800 address of count [ 4 ]= 13522
(* ptr )++ = 801 I incremeted the above value by 1
pointer
( ptr += 1 ) = ptr ++ = 13524

 
This will be explained in the next
. Until then have fun .
In the next tutorials
, I will also be talking about :
  • Pointers and functions
  • Pointers and arrays
  • Pointers and structures
  • Pointers and dynamic memory allocation
  • And other interesting things in C