Topic : A primer on Pointers
Author : saradhi
Page : 1 Next >>
Go to page :


A primer on Pointers



Introduction to & and * operators



Consider the following C declaration.



  int n=4;



This declaration tells the compiler to



Reserve in memory to hold an integer value.
Associate variable name ‘n’ with this memory location.
Store value 4 at the location.


Location name       n

Value at location    4

Location number    4096



The computer has selected 4096 memory location to store the value of n. The location 4096 is a number not to be relied upon, because some other time the computer may choose a different location.



The important point is that n’s address in memory is a number.

We can print the address of n through the following program.



main()

{

  int n=4;

  printf(“Address of n = %u\n”,&n);

  printf(“Value of n is %d\n”,n);

}



The output is



Address of n = 4096

Value n = 4



If you see the first printf() statement you observe that ‘&’ operator is used. The operator ‘&’ is called ‘address of operator’. The expression &n returns the address of variable n. In this case the address happens to be 4096.



The & operator when used with a variable name gives the address of the variable. On the other side of the coin we have another pointer operator ‘*’, also known as ‘value at address’ or ‘indirection operator’.



The ‘*’ operator when used with any ‘address’ gives the value at that address.



Consider the following example.



main()

{

  int n=4;



  printf(“Address of n = %u\n”,&n);

  printf(“Value of n = %d\n”,n);

  printf(“Value at address of n = %d\n”,*(&n));

}



The output would be



Address of n = 4096

Value of n = 4

Value at address of n = 4



Note that printing the value of   *(&n)   is same as printing the value of n.



Pointer expressions


We have now learnt that the address of any variable is also a number. And the expression &n returns the address of n. Hence the address (which is a number) can be stored in another variable saying



p=&n;



But p is not an ordinary variable like any other integer variable. It is a variable which contains an address of another variable ( n in this case).



Since p is a variable, the compiler must provide it space in memory.

Once again the following memory map would illustrate the contents of n and p.



Location name       n                         p

Value at location    4                    4096

Location number    4096              1600



As you can see, n’s value is 4  and p’s value is n’s address.



But we can’t use variable p, without declaring it. And since p is a variable which contains the address of n, it is declared as



int   *p;



The int  * conveys us that the value at the address contained in p is int.



The following program demonstrated the relationships we have been discussing.



main()

{

  int n = 4;

  int   *p;

  p=&n;



  printf(“Address of n = %u\n”,&n);

  printf(“Address of n = %u\n”,p);



  printf(“Address of p = %u\n”,&p);

  printf(“Value of p = %u\n”,p);



  printf(“Value of n = %d\n”,n);

  printf(“Value of n = %d”, *(&n));



  printf(“Value of n = %d\n”,*p);

}



The output would be



Address of n = 4096

Address of n = 4096

Address of p = 1600

Value of p = 4096

Value of n = 4

Value of n = 4

Value of n = 4



If you don’t  understand the program’s output of the meaning of expression &n, &p,*p and *(&p) it is advised to re read from the first.



Pointer declarations


int  *i;

char   *ch;

float   *f;



Here i,  ch,  f are declared as pointer variables capable of holding address. Since addresses are always whole numbers, pointers are always whole numbers.



The essence is “Pointers are variables which contain addresses, and since addresses are always whole numbers, pointers would always contain numbers”



The declaration float   *f does not mean that s is going to contain a floating point value. It means that f is going to contain the address of a floating point variable.



Similarly, char   *ch  means that ch is going to contain the address of a char value. Or in other words, the value at address stored in ch is going to be a char.



Pointer to pointer


We have learnt that a pointer variable contains the address of another variable. Now this variable itself could be another pointer. Thus, we now have a pointer which contains another pointer’s address. The following example should make this point clear.



main()

{



int =3;

int   *j;

int   **k;



j=&i;

k=&j;



printf(“Address of i = %u\n”,&i);

printf(“Address of i = %u\n”,j);



printf(“Address of i = %u\n”,*k);

printf(“Address of j = %u\n”,&j);



printf(“Address of j = %u\n”,&k);

printf(“Address of k = %u\n”,&k);



printf(“Value of j = %u\n”,j);

printf(“Value of k = %u\n”,k);



printf(“Value of i = %d\n”,i);

printf(“Value of i = %d\n”,*(&i));



printf(“Value of i = %d\n”,*j);

printf(“Value of i = %u\n”,**k);



}



The output would be



Address of i = 6480

Address of i = 6480

Address of i = 6480

Address of j = 3276

Address of j = 3276

Address of k = 7200



Value of j = 6480

Value of k = 3276

Value of i = 3

Value of i = 3

Value of i = 3

Value of i = 3



The following memory map will help you identify the relationships between i,j,k.

Location name       i.                                 j                            k

Value at location    4                              4096                      3276

Location number    6480                        3276                      7200



Observe how the variables i,j,k have been declared.



int   i;

int  *j;

int   **k;



Here i  is an ordinary int, j is a pointer to an int, whereas k is a pointer to a pointer to an int.



There is no limit on how far can we go on extending this defining. Possibly till the point we can comprehend it. And that point of comprehension is usually a pointer to a pointer. Beyond this, one rarely requires to extend the definition of a pointer. But just in case…..



Pointer jargon


Consider the following program fragment



int a=35;

int   *b;



b = &a;



Which of the following statements are correct?



b contains address of int.
Value at address contained in b is an int.
b is an int pointer.
b points to an int.
b is a pointer which points in the direction of int.


Well, all the statements are correct. All the statements are trying to establish the same fact, that since b contains an address of int, its an int pointer. Similarly had b contained an address of a float, it would have been a float pointer. With the same argument if we have three pointer variables first containing address of an array, second containing the address of a structure and the third containing the address of a function then it would be appropriate to call these as an array pointer, a structure and a function pointer respectively.



Char, int and float pointers


Consider the following program



main()

{

int i, *ii;

char c, *cc;

flaot f, *ff;



i=32;

c=’A’;

f=3.14;



ii=&i;

cc=&c;

ff=&f;



printf(“Address of i = %u\n”,ii);

printf(“Address of c = %u\n”,cc);

printf(“Address of f = %u\n”,ff);



printf(“Value of i = %d\n”,*ii);

printf(“Value of c = %c\n”,*cc);

printf(“Value of f = %f\n”,*ff);



}



Output



Address of i = 1024

Address of c = 1400

Address of f = 1604



Value of i = 32

Value of c = A

Value of f = 3.140000



Note that in the printf()s the addresses of char, int and the float all have been printed using the format specifier %u. Observe that though the

Page : 1 Next >>