Next:Pointers Up:Main Previous:Programming

Pointers and Arrays

In the previous lecture we saw the basics of how to create a program.

 

We also discussed the  basic structure of a  c-program

 We saw that there are header files in the beginning, then  the variable declaration, constants and then the assignment statements.

 The compilation is done in four stages.  That is when we invoke a compiler, first the a preprocessor checks all the include files, then the variable declarations and in the third stage it generates the code. In the optional fourth stage it rewrites the code to improve the performance, that is optimization.

 Let us also summarize what we saw about the data types. We have the integer, the floating point and the character. In integer, we have long, short and unsigned integer and in floating point we have single precision and double precision.

 When we declare these variables certain locations in the memory is allocated to store the value of it. For example when we say "float x", some space in the memory is reserved to store the value of "x",  when we pass this value to another variable similarly declared, for example in to a sub function which has a variable declared as "float y", we are copying the value stored in one memory location to another. Another way to deal with variable values is to simply work with  a "pointer" to the memory location where the value is stored.  In this case when the variable is passed from "x" to "y" we just tell "y" where in the memory the values is stored, we do not create another storage!

We will now discuss how to use these pointers and what are its special features. We will also introduce the concept of arrays and look at what are the differences between pointers and arrays and how we use them interchangeably  Pointers

 Pointers are variables which point to memory locations. Every pointer has a data type associated with it. It is declared with an asterix (*) before the variable name

 Example:

            Int  number    \*  creates a pointer called number.*/

 It is important here to note that you cannot create a pointer without identifying the data type with which it will be used. In the example above the data type is "integer".

 Here is an example of the use of pointer

 (pointer.c)

#include <stdio.h>

#include <math.h>

main()

{

            float x,y;

            float *z;

            FILE *fp;

FP=fopen("sample.dat","w");

y=10.0;

z=&y;

x=*z;

printf ("\n%f   %f\n ",y,x) ;

}

 

Here "x" and "y" are floating point variables.  We could assign a constant to "y" through the statement  y =10.0.

z" is a pointer, we cannot assign a value to it like in the case of the variable "y".

What we could do it to point "z" to a memory location where a variable is stored.

For example, the statement z=&y,  will make  z a pointer to the address of y.

& is an operator that gets the address of a variable. Once pointed to an address the asterix (*) operator can read of the value stored in that location. For example

  x=*z,  will give  "x" the value that z is pointing to, this is equivalent to the statement  x=y.

 Every variable that we declare has  a name, address and some content.

When we declare int n;  the name is "n" and content is 0. It is stored in a location with an address. To illustrate let us put this address as 16254.  Now a statement  n=6; will change the content to 6. We will now declare another integer "m" as int m; and a pointer with the statement  int *num; . Point "num"  to "n" using num=&n;  then the  resulting table will look something like this.

 

Name    
  Address            
Content
 
16254  
6
 
m  
16256   
0
 
num   
16258       
16254
 

When we said num = &n;, the & operator returned the address of its argument. It sets the content of pointer "num" to the address of the variable n.

Then if m= *num;  the content of m will be changed to 6, because "*num" has the value of "n".  The table is now,

Name
Address  
Content
n    
16254    
6
m     
16256        
6
num    
16258     
16254

 with

 *num               16258                                     6

Here  we have again used the *, the indirection operator which sets the value of "m" to that pointed by "num".

If we compile the program,  "pointer.c",shown above, we see that the values of "y" and "x" are printed out as 10.00000.  Can you explain why ?

Pointers can be used on both sides of the assignment statements

Note that If we have the following statements

            n = 6;

            num = &n;

            m = *num;

it has the same effect as that of

            n=6;

         m=n;

Let us look at the table below, we have a series of three statements here. The intend here is to show the difference between the use of two sets of statements made above.

  The statements n=6;  z=&n;  and m=*z;  will results in ,

assignment    
Name        
Address       
Content
  n=6   
n     
16254       
6
z=&n      
z   
16256      
16254
m=*z          
m   
16256    
6
                  

Now if we change the value of *z, then that will change the value of "n" but not of "m".

We can then look at this using an example, this time for floating points here

 

  (poiner-1.c)

 #include <stdio.h>

#include <math.h>

main()

{

            float x,y;

            float *z;

            y=10.0;

z=&y;

x=*z ;

printf ("\n%f   %f\n ",y,x) ;

*z=9 .0;

            printf ("\n%f   %f\n ",y,x) ;

}

 What will you see if you run this code?

The first print statement will  print 10.0000 for both x and y, and the second statement, after altering the value of *z,  will print x as 10.0000 and y as 9.0000.

Note that x remains unaltered.  This is because  "z" is just pointing to the address of "y" and changing "*z" is same as changing the content at that address.  While x=*z;  is copying the content at that address to that of variable "x".

 Arrays

Array is a collection of data of similar data type. Like pointers array also must have a data type. An integer array, let us say having four elements, can be declared by  "int x[4];". This array can hold 4 different values. The elements of this array are x[0], x[1], x[2], x[3]. Note that the array index starts from 0. C language use [ ] square brackets for arrays, to distinguish it from functions which uses () the parentheses.

An array name is also a pointer to the first element of the array. In the example given above this means that "x" is a point to the array "x[4]".  For example, if we make the following declarations,

             int  x[4];

            int *num;

            num=x;

in a program, "x" is a pointer and is pointing to the element x[0]. The last statement directs the  pointer "num" to point to x[0] too. num++ will set the pointer to the next element of the array and so on. We will discuss more of this pointer arithmetics later in this lecture.

The array elements can be of any of the three types, integer, floating point or character,  that we discuss earlier. We can look at an example which uses an integer array and a character array. Character strings are actually arrays of characters.

 (pointer-2.c)

#include <stdio.h>

#include <math.h>

 main()

{

            float x,y;

long int i, j, k[5] ;

char letter, course = "Numerical Methods";

printf ("\n%c   %s\n ", course[6], course) ;

printf ("\n%c   %s\n ", course[6], &course[0]) ;

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

            {k[i]=3*i;}

j=*(k+2);

printf ("\n%d   %d\n ", k[2], j) ;

}

 First some syntax details: note that when we want to print a character we use %c and when we want to print the string we use %s.

 "course [6]" is the 6th character of the array "course". While we can get the entire array printed if we use "course" and %s  for the format.

 Another important point to note is that the array name is a pointer to itself.  This pointer always points to the first element of the array. So the course and &course [0] will print the same string.

 But an array name  is a constant pointer; we cannot alter the value of it. Its value is always the first element of the array.

 In the next part of the program pointer-2.c , "k" is an integer pointer.

 In the statement "for(i=0;i<=5;i++) {k[i]=3*i;}"  we are populating the integer array in a loop construct. The ith element of this array of six elements will now have a value "3i".

Note the loop construction, all the statements in the { } will be executed for the interval given in the "for" loop.

As we said earlier the array name , here it is "k", point to the element "k[0]". If you want to point to the second element of the array, "k[1]", we use k+1  and the third element is given by k+2  etc .  In general the " (i+1)th " element is given by k+i . As we see in the program we can then print out the elements of the array using this pointer arithmetic.

 In the next line of the program we see the use of asterix (*) operator in use. Since k+2 is pointing to the third element of the array, the statement j=*(k+2);, will assign the value of the third element of the array to "j". This value can be obtained using array indices as k[2]. That is, the statement is same as j=k[2];

      Here is a list of some of the important points about pointers and arrays.

 All pointers are addresses and must be initialized before being used.

 Arrays of pointers:

 We have so far looked at pointers and arrays.  We could also have arrays of pointers. Let us now look at some  examples to get a better feeling for these arrays of pointers.

 (pointer-3.c)

 #include <stdio.h>

#include <math.h>

 main()

{

 float x,y;

long int i, j, m[6], *k[5] ;

char *letter, *course[3], name [ ] = "I I T Madras";

course[0]="Numerical Methods";

course[1]=" and Programming";

printf ("\n%s   %s\n ", course[0], course[1]) ;

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

            m[i]=3*i;

k[0]=&m[1];

k[3]=&m[3];

j=k[3] - k[0];

printf ("\n%d  %d  %d   %d\n ", j, *k, *(k[0]+1), *k[3]) ;

 }

 

This program above has an integer array and an integer array of pointers. It also has a character pointer and an array of character pointers.

 We now make   course [0],the first element of the character pointer array , point to "Numerical Methods" and then course [1], the next element of the array, to point to " and Programming".

 These are character strings, so we use "%s" for the format in the printf statement to print these array elements. When we print it out we get the two strings combined.

 Then we populate an integer array using a for loop. There are five elements in this array with values 0,3,6,9 and 12.  Next we point the first element of the pointer array "k" to the second element of the integer array "m" and the fourth element of "k" to the fourth element of "m". 

 We can now do some pointer arithmetic on it.  For example, if we subtract these two pointer elements we get a number, this is the "distance" between the array elements. In this case j will be 2. The program ends by printing this number j.

This difference between two pointers is useful in finding the length of the string provided the bounds of the array are known.

 Once we have pointed an element of the pointer array to one element of the array "m" we can get the next elements by incrementing the pointer.  This is what is demonstrated using the print statement "printf ("\n%d  %d   %d\n ", j, *(k[0]+1), *k[3]) ;".

Now let us include the following few lines to the above program to see how to connect character pointers and character pointer arrays.

 letter = course [0]

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

{

            j=letter - course [0];

            printf (" %d  %c  \n", j, *letter);

letter++;

}

 Here "letter" will initially point to N, the first element of the string "Numerical Methods" to which "course[0]" is pointing to.

  The difference "letter-course[0]" will be zero at this point.

 Now inside  the "for" loop we will increment the position to which "letter" is pointing by one using "letter++" and print the difference "letter-course[0]" and "j".

 This way we can actually count the number of characters in a string!.

 

Next:Pointers Up:Main Previous:Programming