C Pointers

In this article, you'll learn about pointers; what are they, how do you use them and the common mistakes you might face when working with them.

Pointers are powerful features of C and (C++) programming that differentiates it from other popular programming languages like Java and Python.

Pointers are used in C program to access the memory and manipulate the address.


Address in C

Before you get into the concept of pointers, let's first get familiar with address in C.

If you have a variable var in your program, &var will give you its address in the memory, where & is commonly called the reference operator.

You must have seen this notation while using scanf() function. It was used in the function to store the user inputted value in the address of var.

scanf("%d", &var);
#include <stdio.h>
int main()
{
  int var = 5;
  printf("Value: %d\n", var);
  printf("Address: %u", &var);  //Notice, the ampersand(&) before var.
  return 0;
}

Output

Value: 5 
Address: 2686778

Note: You may obtain different value of address while using this code.

In above source code, value 5 is stored in the memory location 2686778. var is just the name given to that location.


Pointer variables

In C, you can create a special variable that stores the address (rather than the value). This variable is called pointer variable or simply a pointer.

How to create a pointer variable?

data_type* pointer_variable_name;
int* p;

Above statement defines, p as pointer variable of type int.


Reference operator (&) and Dereference operator (*)

As discussed, & is called reference operator. It gives you the address of a variable.

Likewise, there is another operator that gets you the value from the address, it is called a dereference operator  *.

Below example clearly demonstrates the use of pointers, reference operator and dereference operator.

Note: The * sign when declaring a pointer is not a dereference operator. It is just a similar notation that creates a pointer.


Example: How Pointer Works?


#include <stdio.h>
int main()
{
   int* pc, c;
   
   c = 22;
   printf("Address of c: %u\n", &c);
   printf("Value of c: %d\n\n", c);
   
   pc = &c;
   printf("Address of pointer pc: %u\n", pc);
   printf("Content of pointer pc: %d\n\n", *pc);
   
   c = 11;
   printf("Address of pointer pc: %u\n", pc);
   printf("Content of pointer pc: %d\n\n", *pc);
   
   *pc = 2;
   printf("Address of c: %u\n", &c);
   printf("Value of c: %d\n\n", c);
   return 0;
}

Output

Address of c: 2686784
Value of c: 22

Address of pointer pc: 2686784
Content of pointer pc: 22

Address of pointer pc: 2686784
Content of pointer pc: 11

Address of c: 2686784
Value of c: 2

Explanation of the program

  1. int* pc, c;
    A pointer variable and a normal variable is created.
    Here, a pointer pc and a normal variable c, both of type int, is created.
    Since pc and c are not initialized at first, pointer pc points to either no address or a random address. And, variable c has an address but contains a random garbage value.
     
  2. c = 22;
    22 is assigned to variable c.
    This assigns 22 to the variable c, i.e., 22 is stored in the memory location of variable c.
    Note that, when printing &c (address of c), we use %u rather than %d since address is usually expressed as an unsigned integer (always positive).
     
  3. pc = &c;
    Address of variable c is assigned to pointer pc.
    This assigns the address of variable c to the pointer pc.
    You see the value of pc is same as the address of c and the content of pc is 22 as well.
     
  4. c = 11;
    11 is assigned to variable c.
    This assigns 11 to variable c.
    Since, pointer pc points to the same address as c, value pointed by pointer pc is 11 as well.
     
  5. *pc = 2;
    5 is assigned to pointer variable's address.
    This change the value at the memory location pointed by pointer pc to 2.
    Since the address of the pointer pc is same as the address of c, value of c is also changed to 2.

Common mistakes when working with pointers

Suppose, you want pointer pc to point to the address of c. Then,


int c, *pc;

// Wrong! pc is address whereas, 
// c is not an address.
pc = c;  

// Wrong! *pc is the value pointed by address whereas, 
// &c is an address.
*pc = &c; 

// Correct! pc is an address and, 
// &c is also an address.
pc = &c; 

// Correct! *pc is the value pointed by address and, 
// c is also a value (not address).
*pc = c;