Pointers

What is pointer?

A pointer is a special variable that stores the address of another variable.

variable-memory-map

  1. Each variable has a unique address associated with it as shown in the above figure.
  2. To access the variable we use the variable name.
  3. To access the address of the variable we use & (address-of) operator.

The following code snippet shows you how to access the variable's value and variable's address.

printf("value of a = %d\n",a); // value of a = 5
printf("address of a %d",&a); //address of a = 1254

Creating a pointer and storing address

int a = 5;
int *p; //pointer declaration
p = &a;
  1. As shown in the above code snippet, we are storing address of a into another variable p.
  2. As we know if a variable store the address of another variable then it must be declared as pointer variable.
  3. To declare a pointer, variable should be declared with * sign.
  4. The type of the pointer must be same as the type of the variable means a int* can store address of int whereas a float* can store address of float variable.

Accessing variable value using pointer

int a = 5;
int *p; //pointer declaration
p = &a;
printf("%d\n",a); // 5
printf("%d\n",*p); //5
printf("%d\n",*(&a)); //5;
  • After storing address into pointer variable the next thing you should learn that how to access variable's value.
  • To access variable's value using pointer we use another pointer operator * which is known as value at operator or indirection operator.
  • As shown in the statement printf("%d\n",*p); we use *p to access the value of a.
  • *p can be read as value at p or simplified as value at &a.
  • so it can easily observe that *p or *(&a) are the same statement and returns the value at &a means value of a.

Call by reference

As we have already learned that function call be of two types.

  1. Call by value
  2. Call by reference

We have already discussed Call by value in previous chapter. Here we are going to discuss Call by Reference.

Call By Reference

In this type of function call, we pass the address of the variable which is received by a pointer in function definition.

Using pointer we can update the value of actual argument by jumping at the real memory locations and this type of function call is known as call by reference.

Following example demonstrate you how call by reference works...

Program to swap two numbers using pointer

#include<stdio.h>
void swap(int *p1,int *p2) {
	int t;
	t = *p1;
	*p1 = *p2;
	*p2 = t;
}
int main() {
	int a,b;
	
	printf("Enter any two numbers: ");
	scanf("%d%d",&a,&b);
	
	printf("Before swap call...\n");
	printf("a = %d b = %d\n",a,b);
	
	swap(&a,&b);
	
	printf("\nAfter swap call...\n");
	printf("a = %d b = %d",a,b);
	return 0;
}

Output

Enter any two numbers: 8 5
Before swap call...
a = 8 b = 5

After swap call...
a = 5 b = 8

Explanation

  • The main logic behind the above program is that the pointer receives the address of the variable and by dereferencing technique actually jumps to the location of the variable and access/update those values.
  • To achieve the call by reference in the above program, first, we pass the address of the variables a and b from the function call.
  • These addresses are received by pointers p1 and p2 on the function definition.
  • To swap the value of a and b, the first statement is t = *p1; which is equivalent to t = a;
  • In the second statement we update the value of a with the value of b by using the statement *p1 = *p2;
  • And finally, copy the value of a that is stored into variable t into b by using the statement *p2 = t;

Key-points about pointer

Each pointer require only 2 bytes or 4 bytes memory based on the compiler.
  1. Each pointer stores address and address is always a positive integer means unsigned integer.
  2. To store unsigned integer only 2 bytes (16 bits) required on 16-bit compilers and 4 bytes (32 bits) on the 32-bit compiler.
  3. So it is clear that each pointer requires only 2 bytes or 4 bytes memory based on the compiler.

The type of the pointer must be the same as the type of the variable which is pointed by the pointer.

  1. As pointer always stores address means an unsigned integer but pointer type shouldn't be always int.
  2. Actually, pointer type doesn't specify, what pointer stores, it specify to the type of the variable that is able to access by the pointer.

Uses of pointer

  1. A pointer is used in the call by reference.
  2. A function can't return multiple values but if you want to create a function that works similar to a function that returns multiple values can be done by using pointers. The following example demonstrates returning multiple values from a function.

Program to returning multiple values from a function

#include<stdio.h>
void sumavg(int x,int y,int *p1,float *p2) {
	*p1 = x + y;
	*p2 = (x + y)/ 2.0f;
}
int main() {
	int a,b;
	int sum; float avg;
	
	printf("Enter any two numbers: ");
	scanf("%d%d",&a,&b);
	
	sumavg(a,b,&sum,&avg);
	
	printf("Total = %d\n",sum);
	printf("Product = %.2f\n",avg);
	return 0;
}

Output

Enter any two numbers: 5 6
Total = 11
Product = 5.50

Explanation

  1. As we know a function can't return multiple values, but sometimes if needed to do the same then it can be done in another way by using a pointer.
  2. Suppose if a function return multiple values, then it is received by some variables as in the above program sum and the average of a and b should be stored sum and avg variable created in main.
  3. Now a function can't return multiple values but can update variables value by using pointers.
  4. So in the above program, we pass the address of sum and avg from main and in function sumavg these addresses received by pointers p1 and p2.
  5. Finally, update the sum of a and b at the address of sum and average of a and b at the address of avg.
  6. In this way, we can simulate a program that returns multiple values.

Pointer to pointer

As a pointer can point the address of another variable similarly a pointer can hold the address of another pointer.

int *p1;
int a = 10;
p1 = &a;

As the above code snippet shows that variable p1 is storing the address of integer variable a, so it is declared as int* (integer pointer).

int *p1;
int a = 10;
p1 = &a;

int **p2;
p2 = &p1;
printf("%d",*p1); // 10 (value of a)
printf("%d",*p2); // prints the value of p1 that is &a (address of a).
printf("%d",**p2);// 10 (value of a)

We extend the previous code snippet and in the above code snippet, a pointer p2 wants to store the address of pointer p1. so it should be declared as pointer to integer pointer means a double pointer (int **).

The same concept can be followed till triple pointer and so on.