14 - C Pointers

This chapter will introduce pointers. Pointers are very important when you undertake C programming. Pointers can be daemons and angels according to the usage in C programming. In other words, if you are expert in handling pointers that means you are unbeatable and if you fail to use pointers the way they are meant to be then pointers can be very dangerous. Last chapter was dedicated to arrays. Memory of computer is organized as contagious locations in array. Every location has an identification number and this identification number is known as Address. Now, pointers hold the address. So a pointer can be rightly defined as a placeholder/variable which contains memory location of the variable rather than its content. Pointer is a derived data type. If size of RAM is 64K then pointer can take value from 0 to 65535. In other words, pointers point to variables and those variables can be:

  • int, float, char, double, void (basic data types)
  • function
  • array
  • structures
  • unions

You must be thinking that the concept which is apparently a daemon if not used correctly then why we should read this concept? So the answer is it advantages so let us have a glance on the advantages of pointers and they are:

  • Pointers can point to various data structures
  • Since pointers handle addresses directly so the manipulation of data at various locations of memory is easy
  • When pointers are used in proper way they improves the simplicity of program
  • Coding is more efficient and compact when we use pointers
  • With the use of pointers we can return multiple results from same function
  • Pointers makes dynamic memory allocation possible

14.1 Pointer Constants, Pointer Values and Pointer Variables

Pointers have three major concepts and they are pointer constants, pointer values and pointer variables

14.1.1 Pointer Constants

Computer stores all the information in its memory like we do. Locations in memory are limited and memory is divided into smaller units called Storage Cells. Each storage cell can hold information of one byte. Each storage cell/location has an associated address. Now, 1K equals to 1024 bytes. Number of memory locations would be 64K. We will have 64 x 1K which equals to 64 x 1024 bytes = 65536 locations (if assumed capacity of memory is 64K).

Don't worry these many memory locations are organized physically as even and odd bank respectively but logically they are numbered from 0 to 65535. As the name suggests, odd bank contains all memory locations with odd addresses and even bank contains even addresses respectively.

                    Figure -  Even and odd bank

Memory addresses cannot be changed. As a programmer, you can only use them to store values of data and these memory addresses are known as Pointer Constants.

 

14.1.2 Pointer Values

Pointer values are assigned by system. We have 65536 Pointer constants in a 64K memory. System assigns these memory addresses to variables and these memory addresses which are assigned to variables by system are called Pointer Values. 

Example: int x=50, y=60; 

Explanation: In the above declaration, system is instructed to reserve two integer values in memory.                                  Then associate variables x and y to these memory locations and finally store 50 and 60                                in locations x and y respectively. In the memory map it would look as follows:

 C Pointer Values

                       Figure -  C Pointer Values

 

Now address of variable can be accessed and this is possible by using (&) address operator. Now there is a thumb of rule in the usage of address operator. It can be used with only those variety of variables which are valid when they are placed on the left side of assignment operator. So in short, we cannot use address operator with constant, expression and names of array. Now constant and expression can be understood what about array? Array is an user defined data type which has similar set of data items and to point to an array we have a way. For example we have array named arr, then we can address first location of array which can be obtained using following expression:

               &arr[0] or arr 

Let us consider that 65532 and 65534 are the memory locations assigned to variables x and y respectively. And these addresses can be retrieved by using address operator (&) and in the above scenario it would be &x and &y respectively. Pointer vales are not constant vales. They may be different after each execution of program. 

14.1.3 Pointer Variables

Pointer variable is defined as a variable which holds address of different variable. In terms of pointer values, pointer variable hold the address of pointer value and as you know pointer value is the address of another variable.

Example: int x=50; and p=&x; 

Explanation: in the above scenario, p is the pointer variable and address of variable x is stored in p.

Figure – C Pointer variable and pointer value (physical representation in memory)

Figure – C Pointer variable and pointer value (logical representation)

Here, address of variable x (65534) is assigned to variable p. Now  the address of variable p itself is 60000 but the value stored in this variable is the address of variable x which is 65534. Variable p is our pointer variable. And variable p points to x thus called pointer. Pointer variable can only hold the address of other variable.

 

We have two operators used with pointers and they are:

1.Ampersand or Address operator (&)

2.Asterisk or Indirection operator (*)

 

14.2 Pointers and accessing variables

We have a series of steps which are required to access variables via pointers and they are as follows:

1.A data variable has to be declared before using it

2.Pointer variable has to be declared

3.Pointer variable need to be initialized

4.Data can be accessed via pointer variable

 

14.2.1 Declaring and defining pointer

We need to declare pointer variable before using it. Format is as follows:

     data_type * identifier ;

Explanation: Here,

          data_type is the data type which can be either basic (int,float,char,double), derived or user-defined.

           identifier represents the name of pointer variable

* represents that identifier is a pointer variable

 

Next, step is to initialize the pointer variable. Here first we will have to declare a data variable followed by declaring pointer variable and then we initialize the pointer variable. In other words, when we talk about initialization, we mean associating address of an variable to pointer variable.

Step1: int y;       //declaring data variable

    Step 2: int *p;    //declaring pointer variable

      Step 3: p=&y;    //initializing pointer variable

 

One pointer can point to more than one memory location so it improves flexibility of programming. Let us consider the following program snippet.

Example: int i=12, j=14, k=16, l=18;            

                 int *p;                                                                                                        

                 p=&i;                                                               

                 // other statements

                 p=&j;                                                                                             

                 // other statements

                 p=&k;                                                                                                                    

                 // other statements                                                                                                  

                 p=&l;

                 // other statements   

C Logical Representation

     C Logical Representation

 

Explanation: In the above scenario, we can see same pointer variable p is pointing to four different  memory locations. Hence we can say same pointer can be used to point different data variables.

 In this scenario, we have one important concept for study and that is NULL pointer. This does not point to any memory location. Then why we need this, isn't it!! This is useful when you have lot of pointers to manage or if you are at initial stage of coding where you have not reached the stage of assigning the address of a variable to the corresponding pointer variable, in that case it is better to initialize pointer variable as NULL pointer. This is going to avoid to use of uninitialized pointers as it an compilation error. NULL is defined in “stdio.h” header file. So a NULL pointer looks as shown below: 

# include <stdio.h>

int *q=NULL; 

Here, pointer q is initialized to NULL ('\0' or 0) and it can be used by programmer to access data variable if and only if it does not contain NULL. 

Suppose you declare a pointer variable and fail to initialize it or in other words which does not have a valid address then this type of pointer is called Dangling pointer. Memory location will be allocated but as it was not initialized then this type of pointer will result in garbage value in memory. Dangling pointers should be avoided as these errors are very difficult to debug when you deal with lot of pointers or pointers in large and/or complex programs. 

We can also access data of a variable using pointers. Asterisk (*) operator is used for this purpose. Consider the following snippet: 

Example: int y=50;

                  int z;

                  int *p;

                  p=&y;

                  z=*p;

 Explanation: Here, we have a two data variables, namely y and z which are of integer type  respectively. Now, y is initialized to 50. We have a pointer variable, p. Address of variable is stored in pointer variable p. In other words, address of y is stored in p. Now pointer p contains address of y and the value of variable y which is 50, copied into z.

 Now if you remember, we saw one pointer can point to different variables, similarly, one variable can be pointed by different variables. Do not worry! Let us consider the following snippet:

     Figure – C Logical Representation 2

Explanation: In the above scenario, we have three pointer variables namely x, y and z which are of  type integer. We have a data variable r which is also of type integer is initialed to 50.   

Pointers x, y and z point to same address of variable r respectively. 

Let us consider a simple program illustrating the usage of pointers so that we can actually see the practical implementation of pointers. 

/* Program to illustrate pointers*/

# include <stdio.h>
# include <conio.h>
# include <stdlib.h>

int * largestnumber (int *x, int *y)
 {
  if(*x > *y)
    return x;
  else
    return y;
 }
void main()
 {
  clrscr();
  int i, j, *large;

  printf("Please enter two values\n");
  scanf("%d%d", &i,&j);
  large=largestnumber(&i,&j);
  printf("Largest of two numbers (%d,%d)=%d\n", i,j,*large);
  getch();
}

 C Program to illustrate pointers

                  Figure – C Program to illustrate pointers

Figure - After compiling C Program to illustrate pointers

     Figure - After compiling C Program to illustrate pointers

        Figure - Output of  C Program to illustrate pointers

 Folks!! We are concluding this chapter with this. Next chapter is dedicated to strings. Thank you.

Like us on Facebook