Pointers And Arrays 


An array is a collection of similar elements stored in adjacent memory locations. 
 

int a[] = { 10, 13, -24, -35, 67 } ; 

float b[] = { 1.2, 3.44, -5.44, 6.7, 8.9 } ; 

long int c[25] ; 

If an array is defined and initialized at the same place mentioning its dimension is optional. 

If similarity and adjacency considerations are met we can build an array of anything, like say, an array of doubles,  an array of structures, an array of pointers etc. 

Size of an array is sum of sizes of individual elements of an array. 

Base address of an array if address of zeroth element of the array. 

Mentioning the name of the array fetches its base address.
 

int a[] = { 10, 13, -24, -35, 67 } ; 

printf ( "%u %u", a, &a[0] ) ; // both would give base address

Array can be passed to a function element by element. Alternatively we can pass the entire array to a function at one shot.
  

int a[] = { 10, 13, -24, -35, 67 } ; 

int i ; 

 

// passing the array element by element 

for ( i = 0 ; i < 5 ; i++ ) 

display ( a[i] ) ;
 

// passing entire array 

show ( a, sizeof ( a ) / 2 ) ; 

To pass an entire array we simply need to pass its base address. Whenever we pass an entire array to the function we also need to pass the size of the array, since the function has no way to find  out how many elements are present in the array. 

Array elements can be accessed using the subscript notation or the pointer notation. 

int a[] = { 10, 13, -24, -35, 67 } ; 

int i ; 

 

// access using subscript notation 

for ( i = 0 ; i < 5 ; i++ ) 

printf ( "%d", a[i] ) ; 

 

// accessing using pointer notation 

for ( i = 0 ; i < 5 ; i++ ) 

printf ( "%d", * ( a + i ) ) ; 

Subscript notation is converted by the compiler into the pointer notation. Hence pointer notation would work faster since using it we would be able to save on  the conversion time. 

All four following expression are same:
 

a[i]  

* ( a + i ) 

( * i + a )  

i[a] 

In the expression a[i] 

Out of a and i one must be an integer. The other may either be an array name or a pointer. 

An array of pointers is different than a pointer to an array.
 

int *a[10] ;   

int ( *b )[10]

a is an array of pointers, whereas, b is pointer to an array. Incrementing a using a++ is illegal. On incrementing b it would start pointing to the  next location of its type. 

What would be the output of following program
 

main( )  

{  

 

int arr[ ] = { 0, 1, 2, 3, 4 } ;  

int *ptr ;  

for ( ptr = arr + 4 ; ptr >>= arr ; ptr-- )  

printf ( "%d ", arr [ ptr - arr ] ) ;  

 } 

Output  
4 3 2 1 0  

Explanation  
A picture is worth a thousand words. Going by this dictum, the following figure 1 should add clarity to your understanding  of the program. 


Figure 1.  

Now things are getting really complicated, as the printf( ) would justify. Let us begin with the for loop. Firstly ptr is assigned the address 6012, the address of the fourth integer from the base address. Since this address is greater than the base address, the condition is satisfied and the control reaches printf( ) . What does arr [ ptr - arr ] evaluate to? ptr - arr means 6012 - 6004 , which yields 4, and hence arr[4] prints out the fourth element of the array. Then ptr-- reduces ptr to 6010. Since 6010 is greater than the base address 6004, the condition is satisfied and once again the control reaches the printf( ) . This time ptr - arr becomes 6010 - 6004 , i.e. 3. Thus arr[3] prints out 3. This process is repeated till all the integers in the array have been printed out. Possibly an easier way of understanding the expression ptr - arr would be as follows. Suppose ptr contains 6012 and arr contains 6004. We can then view the subtraction as ( arr + 4 - arr ) , since ptr is nothing but arr + 4 . Now I suppose its quite logical to expect the result of the subtraction as 4.  

What would be the output of following program

main( )  

 { 

static int a[ ] = { 0, 1, 2, 3, 4 } ; 

static int *p[ ] = { a, a + 1, a + 2, a + 3, a + 4 }  

int **ptr = p  

printf ( "\n%u %d", a, *a )  

printf ( "%u %u %d", p, *p, **p )  

printf ( "\n%u %u %d", ptr, *ptr, **ptr ) ;

Output   
6004 0  
9016 6004 0  
9016 6004 0 

Explanation   
Look at the initialisation of the  p[ ] . During initialisation, the addresses of various elements of the array  a[ ]  are stored in the array  p[ ] . Since p[ ] contains addresses of integers, it has been declared as an array of pointers to integers. Figure 2 shows the content  a[ ]  and  p[ ] . In the variable  ptr , the base address of the array  p[ ] , i.e. 9016 is stored. Since this address is the address of  p[0] , which itself is a pointer,  ptr  has been declared as pointer to an integer pointer. Let us understand the  printf( )  now. The first  printf( )  is quite simple. printf ( "\n%u %d", a, *a ) ; It prints out the base address of the array  a[ ]  and the value at this base address.  


 Figure 2  

Looking at the figure 2, this would turn out to be 6004 and 0. When you execute the program, the address may turn out to be something other than 6004, but the value at the address would be surely 0. 

Now look at the second printf( ) .  
printf ( "\n%u %u %d", p, *p, **p ) ;  

Here  p  would give the base address of the array  p[ ] , i.e. 9016;  *p  would give the value at this address, i.e. 6004;  **p  would give the value at the address given by  *p , i.e. value at address 6004, which is 0. Now onto the last  printf( ) .  

printf ( "\n%u %u %d", ptr, *ptr, **ptr ) ;  

Here  ptr  contains the base address of the array  p[ ] , i.e. 9016;  *ptr  would give the value at this address, i.e. 6004;  **ptr  would give the value at the address given by  *ptr , i.e. value at address 6004, which is 0.

What would be the output of following program
 

main( )  

{  

static int a[ ] = { 0, 1, 2, 3, 4 } ; 

static int   *p[ ] = { a, a + 1, a + 2, a + 3, a + 4 } ; 

int **ptr = p ; 

 

ptr++ ; 

printf ( "\n%d %d %d", ptr - p, *ptr - a, **ptr ) ; 

 

*ptr++ ; 

printf ( "\n%d %d %d", ptr - p, *ptr - a, **ptr ) ; 

 

*++ptr ; 

printf ( "\n%d %d  %d", ptr - p, *ptr - a, **ptr ) ; 

 

++*ptr ; 

printf ( "\n%d %d  %d", ptr - p, *ptr - a, **ptr ) ; 

}  

Output  
1 1 1  
2 2 2 
3 3 3 
4 4 4 

Explanation  
Figure 3 would go a long way in helping to understand this program. 

Here  ptr  has been declared as a pointer to an integer pointer and assigned the base address of the array  p[ ] , which has been declared as an array of pointers. What happens when  ptr++  gets executed?  ptr  points to the next integer pointer in the array  p[ ] . In other words, now  ptr  contains the address 9018. Now let us analyse the meaning of  ptr - p ,  *ptr - a  and  **ptr . 

 ptr - p  

Since  ptr  is containing the address 9018, we can as well say that  ptr  is containing the address given by  p + 1 . Then  ptr - p  is reduced to  ( p + 1 - p ) , which yields 1. 

 *ptr - a ; 

*ptr  means value at the address contained in  ptr . Since  ptr  contains 9018, the value at this address would be 6006. Now 6006 can be imagined as  ( a + 1 ) . Thus the expression becomes  ( a + 1 - a ) , which is nothing but 1. 

 **ptr  

ptr  contains 9018, so  *ptr  yields 6006, and hence  **ptr  becomes  *( 6006 ) , which yields 1.

Thus the output of thefirst ; printf( )  becomes 1 1 1.  

Take a deep breath and then begin with the analysis of  *ptr++ . Here  *  and  ++  both are unary operators. Unary operators have an associativity of right to left, hence  ++  is performed before  * .  ++  increments  ptr  such that  ptr  now contains 9020. Then  *( 9020 )  is performed, which gives the value at 9020. But since this value is not assigned to any variable, it just gets ignored. Now with  ptr  containing 9020, let us once again analyse the expressions  ptr - p ,  *ptr - a  and  **ptr .  


 Figure 3.

ptr - p  

Since  ptr  contains 9020, it can be visualised as  ( p + 2 ) . Thus  ptr - p  would become  ( p + 2 - p ) , which gives 2. 

 *ptr - a  

 *ptr  would give value at address 9020, i.e. 6008, which is nothing but the address given by  a + 2 . Thus the expression becomes  ( a + 2 - a ) , which gives 2. 

 **ptr 

 *ptr  gives the value at address 9020, i.e. 6008, and  *( 6008 )  gives the value at 6008, i.e. 2. 

I hope your confidence is building and you are ready to meet head on the expression  *++ptr . Here, since  ++  precedes ptr , firstly  ptr  is incremented such that it contains the address 9022, and then the value at this address is obtained. Since the value is not collected in any variable, it gets ignored. Now having cooked enough pointer stew you can easily imagine that the output of the third  printf( )  would be 3 3 3. 

Finally, let us understand the expression  ++*ptr . Here obviously, the priority goes to the  * . Thus, this expression increments the value given by  *ptr . Since  ptr  contains 9022,  *ptr  gives value at 9022, i.e. 6010. This value is incremented to 6012.  

So  p[3]  now contains 6012, whereas value of  ptr  remains stationary at 9022. Let us now analyse the expressions  ptr - p ,  *ptr - a  and  **ptr . 

ptr - p  

ptr  contains 9022, therefore  ptr  can be imagined as  ( p + 3 ) . Thus  ( ptr - p )  becomes  ( p + 3 - p ) , which yields 3. 

*ptr - a 

*ptr  yields 6012 which can be thought of as  ( a + 4 ) . Thus the expression is reduced to  ( a + 4 - a) , which yields 4.

**ptr  

*ptr  yields 6012, therefore  **ptr  would yield the value at  *ptr , or the value at 6012, which is >4.

Back


Home | Online Courses | Free C Source Code | Free VC++ Source Code | COM/DCOM Stuff |  Courses@Nagpur | Project Ideas | Ask Queries | COM FAQs |  Conferences | Discussion Board | Previous Weekly Updates | Good Books | Vedic Maths | Time Pass |  Submit Code | About Us | Advertise | Disclaimer  


 Designed and Managed by
DCube Software Technologies, Nagpur (India) 
Last Revised: 10 May 2000 21:27:20