Introduction to Pointers


A type of variable that is used to store the memory address of a memory cell is known as pointer. It normally stores the memory address of a variable or object. The data type of a pointer must be same as the data type of the variable whose memory address is stored in pointer. In C programming language we can refer a variable indirectly that is by using its address.

NOTE: A pointer can be a NULL pointer and its value is zero.


Benefits of using Pointers:

  1. Pointers are used to handle arrays and structures as they are more efficient.
  2. We can call a function by reference by using pointers.
  3. The lines of code become less when we are using pointers.
  4. Dynamic memory can be managed by C programming language if we are using pointers.

Uses of Pointers in C:

Functions or modules in C programming language use arguments or parameters, to which the user has to pass values. Sometimes, it becomes difficult to pass the values of the parameters; in such cases pointers are used.

Pointers are also often used to return more than one value from a function.

Concept of Pointers:

When we create a variable a memory location is allocated to it. This memory location holds the value of the variable. The pointer is a variable which holds this address.


Declaring Pointers:

We have already learnt that to use a variable in a program, we have to declare it first else the compiler will generate an error message. Likewise, pointers are also declared before using in the program, this will also help the compiler to know how much memory is allocated to the pointer. For simple variables we use data types to define them. You may regard that a pointer also has a data type, the syntax to define or declare a pointer is as follows:

SYNTAX:

Data_type *variableName;

Data_type is the primitive type that can be an integer.

‘*’ Indicates that the declared variable is a pointer.

VariableName is the name of the variable.

Pointer can also be declared using the keyword “ptr” that is

ptr a, b;

This allocates two bytes of the memory to the pointer variable. In C programming instead of using the “ptr”, we use ‘*’ for the pointers. Ptr is used at the beginning of the pointer variable declaration but ‘*’ is used immediately before the pointer variable.

NOTE: ‘*’ is a unary operator that is it works only on one operand. (Such as *a)

The following figure demonstrates the concept of pointers:

The following figure demonstrates the concept of pointers

Void point

In the above example x and y are pointer variables, the function is called by the two addresses ‘&a’ and ‘&b’, the control is transferred to the function and these addresses too. In the function these addresses are stored in the pointer variables.

Initialization of Pointer variable:

In initialization of pointer variables we assign some value to pointer variables. A pointer variable has the address of variable of same data type. In C programming language we use the “&” operator to determine the address of a variable. Consider the following example in which a pointer is declared and later it is being initialized:

CODE:

int x = 10 ;

int *ptr ;       // declaration of pointer

ptr = &x ;    // initialization of pointer

We can also initialize a pointer variable when it is declared; consider the following line of code:

int *ptr = &a ;

A pointer variable should be of same data type to which it is referencing. If the data type of the pointer variable is different from the variable for the address of which it is used then compiler will generate an error. Consider the following lines of code:

CODE:

float x;

int *ptr;

ptr = &x;      // Error, type mismatch error

Dereferencing of Pointer:

When we assigned a pointer the address of a variable and want to access the value of the variable then the pointer is dereferenced. This is done by using the indirection operator that is *.

Consider the following example in which we have done this:

CODE:

int x,*p;

x = 5;

p = &x;

printf (“%d”,*p);   // the value of x will be printed

printf (“%d”,*&x);  // again value of x will be printed

printf (“%u”, &x);  // here address of x will be printed

printf (“%u”, p);  // again address of x will be printed

printf (“%u”, &p);  // again address of x will be printed


Pointer and Arrays:

Pointers and arrays are sometimes used together to get the address of the variable and its value at the same time to print the addresses of variables. Consider the following example in which the address of a variable is printed by using arrays:

CODE:

# include <stdio. h>

# include <conio. h>Addresses of variables

void main ()

{

int array [2];

printf (“addresses of variables”);

for (int i = 0; i < 2; i ++)

{

printf (“%d\n”, &array [i]);

}

The address of the array is simply printed by using ‘&’ with the array variable.

Now consider the following example in which we have printed the address of variable by using pointers:

CODE:

# include <stdio. h>

# include <conio. h>

void main ()Address of second element of the array

{

float array [2];

float *point;

point = array [1];

printf (“address of second element of the array = %f”, point);

}

The line point = array [1] shows that we are referring to the second element of the array that is array [1]. In the printf statement the address is printed.

Pointer to array:

A pointer in C programming language can point to an array. This pointer then can be used to access the array. Consider the following example:

CODE:

int i;

int array [5] = {1, 2, 3, 4, 5};

int *p = array;  // it can be written as int*p = &a [0]

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

{

 printf (“%d”, *p);

 p ++;

}

In the above example the pointer p can be used to print all the values that are saved in the array one by one. In the above printf statement if we use

printf (“%d”, array [i]) then the whole array will be printed while the index will also incremented. In the above example if we use:

printf (“%d”, i [array]) this will also print the elements of the array.

If we use printf (“%d”, array + i) then the address of all elements of the array will be printed.

If we use printf (“%d”, *(array +i)) this will print the value of the array.

If we use printf (“%d”, * array) then only the value at index 0 will be printed.

If we use array ++ then there will be a compilation error as the base of the array cannot be changed.

Pointer to Multidimensional Array:

A multidimensional array in C programming language is in the form of a [i][j] where i is the number of rows and j is the number of columns. In the array a[i][j], a will give the base address of the array. The address of a [0][0] will also give the base address of the array. Consider the following line of code which demonstrates that how to use pointer with multidimensional array:

* (* (ptr + i) + j)

This expression is the same as:

a [i][j];

Pointer and character strings:

In C programming language we can also use pointers to create strings. The pointer variables that are of character type are treated as strings. Consider the following line of code:

char *s = “Programming”;

This line of code is creating a string and storing address in the pointer variable s. The pointer variable that is s is pointing to the first character of the string that is P. We can also assign a value to character pointer at run time.

Array of Pointers:

In C programming language an array can be of pointer. We mostly use pointers to handle character array that will have rows of varying length. Consider the following example:

CODE:

char *name [3]={“Stuart”, “Bill”, “James”};

char name[3][20]= { “Stuart”, “Bill”, “James”};

In the above example we have two statements. In the first statement pointer is used with array and only three locations will be allocated to pointer. This will point to the first character of the respective string. In the second statement we did not use any pointer rather multidimensional array is used. This will store all the characters of all names and the memory location will be extended from 20. By using multidimensional array more memory space will be wasted because of this we use arrays of pointers.


Pointer to structure:

In C programming language we can have array of structure variables just like array of integers or array of pointers, etc. To make use of array of structure variables more efficient we use pointers of structure type. Consider the following example:

CODE:

struct Book

{

 char name [10];

 int price;

}

void main ()

{

 struct Book b;     // structure variable

 struct Book * ptr;   // structure type pointer

 ptr = &b;

 struct Book b1 [10];   // structure array variable

 struct Book * p;     // structure type pointer

 p = &b1;

}

Accessing Structure Members with Pointers:

The dot (.) operator is used to access the members of structure with structure variable. If we have pointer of structure type then we use the (->) to access the members of structure. Consider the following example:

CODE:

struct Book

{

 char name [5];

 int price;

}

void main ()

{

 struct Book b1;

 struct Book * ptr = &b1;

 ptr -> name = “Bill”;

 ptr -> price = 500;

}


Pointer Arithmetic:

To understand pointer one should have complete knowledge of pointer arithmetic. In this section we will learn how the memory addresses change when a pointer is incremented.

16 bit Machine:

The size of all the types of pointer that are int*, float*, char*, double* is always 2 bytes in a 16 bit machine. When an increment is performed on the pointer a change is occurred on the size of the pointer. Consider the following table in which the size of the data types is displayed on the 16 bit machine:

Type Size in bytes
int 2
char 1
long 4
float 4
double 8
long double 10

Examples for Pointer Arithmetic:

Consider the following example in which the pointer is of 2 bytes and when the pointer is incremented, it will be incremented by 2 bytes as int is of 2 bytes:

int* x;

x ++;

Now consider the following example in which the pointer is of float data type but has 2 bytes but when it is incremented the pointer will be incremented by 4 bytes because of float data type:

float* x;

x ++;

Similarly if we have a pointer of double data type, when the pointer is incremented it will be incremented by 8 bytes.

32 bit Machine:

In the 32 bit machine the concept of pointer arithmetic is the same but the size of the pointer increases and some of the data types are different in the 32 bit machine. A pointer in the 32 bit machine is of 4 bytes. . Consider the following table in which the size of the data types is displayed on the 32 bit machine:

Type Size in bytes
int 4
char 2
long 8
float 8
double 16


Pointer as Function Parameters:

In C programming language we use pointer as he parameter of the function to hold the address of the argument that is passed in the function call. This process is called calling function by reference. When we call a function by using reference then changes to reference variable will also change the original value of the variable.

Example:

Consider the following example in which we have sorted an array of elements by using pointers:

CODE:

# include <stdio. h>

# include <conio. h>

void sort (int *x, int y);

void main ()

{

 int arr [5], q, w;

 clrscr ();

 printf (“Enter 5 numbers”);

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

 {

  scanf (“%d”, &arr [q]);

 }

 sorting (arr, 5);

 getch ();

}

void sort (int *x, int y)

{

 int i, j, temp;

 for(i = 1; i <= y – 1; i ++)

 {

  for (j = 0; j * (x+j+1))

   {

    temp = * (x + j);

    *(x + j) =*(x + j + 1);

    *(x + j + 1) = temp;

   }

  }

 }

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

 {

  printf (“\t%d”, *(x + i));

 }

}

In the above example the array is sorted by using a pointer as a function parameter and array is used as function argument.


Function returning pointer:

In C programming language a function can return a pointer to its call. But the pointer should not be connected to the local variable of the function as the local variable is not known outside the function. Consider the following example:

CODE:

# include <stdio. h>

# include <conio. h>

int* large (int* x, int* y);

void main ()

{

 int q = 5;

 int w = 2;

 int *point;

 point = large (&q, &w);

 printf (“%d is larger”,*point);

}

int* larger (int *x, int *y)

{

 if (*x > *y)

  return x;

 else

  return y;

}

In the above example we are finding the larger of two numbers by passing the pointer to the function. It can be seen that the return type of the function is pointer which means that the function is returning pointer during function call and this pointer will be stored in the pointer type variable p which will be then printed by using the printf statement.


Safe ways to return a valid Pointer:

The safest ways to return a valid pointer in C programming language are as follows:

  1. By using arguments with function. As the arguments are passed to function and are declared inside the calling of the function therefore they are known outside the function call as well.
  2. By using static local variables. We can use the static local variables inside the function and return them. We will use static local variables as they have a lifetime until the main () function exits therefore, the static variables will live throughout the program.


Pointer to functions:

In C programming language we can use pointers to point to a function. The pointer will be used as an argument in another function. The following is the syntax to pass pointer to a function:

type (* pointer name) (parameter);

Consider the following example in which we have passed pointer to function:

int (* add) ();

int * add ();

We can point to a specific function by using function pointer. This can be done when we assign the name of the function to that specific function. Consider the following example:

int add (int, int);

int (*a) (int, int);

a = add;

In this example a is the pointer to the function named add. Now we can call the function add by using the function pointer a enclosed in parenthesis with the list of parameters as follows:

a (3, 4);


Example of Pointer to Function:

Consider the following example in which we have used pointer to point function:

CODE:

# include <stdio. h>

# include <conio. h>

int add (int a, int b)

{

 return a + b;

}

void main ( )

{

 int (*f) (int, int);

 f = add;

 int a1 = a (15, 15);

 printf (“Sum is %d”, a1);

 getch ();

}

OUTPUT:

30


Complicated Function Pointer Example:

Consider the following example:

void * (* f) (int *);

This statement seems very complicated but it is not. In this line of code f is the pointer to the function and the return type of the function is void * and the argument of the function is of int* type.