C++ Pointers

A pointer in C++ allows us to directly access data stored at a particular memory location. Pointers are one of the most powerful feature of C++ programming language. Once you master the use of pointers, you will use them everywhere to make the code more efficient and faster. In C++, some operations can be performed more efficiently using pointers like dynamic data structures like linked list and trees,dynamic memory allocation, pass arguments to a function as Call by Reference, access array elements etc.

What is a Pointer

A pointer in C++ is a variable which is used to store the address of another variable.

A variable in C++ is the name given to a memory location, where a program can store data. A program can manipulate the value stored using variable's identifier. When we declare a variable in C++, compiler allocates sufficient space in memory to store the value assigned to this variable. We can access the value of this variable either by variable identifier or by directly accessing the memory location using pointers.

Every memory location is given a unique address, once you know the address of a memory location(variable), you'll then be able to go to that address and manipulate the data stored in it. To get the address of any variable, we can use &(Address of) operator and to retrieve the value stored at a memory location we can use *(Value of Operator).

  • If count is a variable then, &count gives the memory address of count variable.
  • If ptr is a pointer variable storing the address of a memory location then *ptr gives the data stores at memory location pointed by ptr.

Advantages of Pointers
  • We can dynamically allocate or deallocate space in memory at run time by using pointers.
  • We can pass arrays to a function as call by Reference.
  • The use of pointers results into faster execution of program.
  • Using pointers we can return multiple values from a function.
  • Pointers in C++ are used to efficiently implement dynamic Data Structures like Queues, Stacks, Linked Lists, Tress etc.
  • Pointers are used to efficiently access array elements, as array elements are stored in adjacent memory locations. If we have a pointer pointing to a particular element of array, then we can get the address of next element by simply incrementing the pointer.

Reference operator (&) and Deference operator (*)

The & is a unary operator in C++ which returns the memory address of a variable. This is also known as address of operator.

The * is a unary operator which returns the value stored at a memory location which is pointed by a pointer variable. It is known as "value of" operator. It is also used for declaring pointer variable.

For Example :
    int A = 100;
    int *ptr = &A;
    cout << *ptr;

In the first statement, we first declare an integer variable and initialize it with value 100. In second statement, we are declaring a pointer to a variable of type int and initializing it with address of A. The third statement prints the value stored at the memory location pointed by ptr, which is 100.


Pointer Declaration

A pointer is a derived data type that is created from fundamental data types. We use (*) for defining pointer variables. Here is the syntax of declaring a pointer variable.

<data_type> *<identifier>;
For Example :
int *ptr;

Above pointer declaration specifies that, ptr is a pointer variable that will store the memory address of an integer. We can also initialize a pointer as follows:

    int age = 10;
    int *ptr = &age;

Integer variable 'age' is the name to a memory location where value 10 is stored. Let the memory address of age is "0x52436721". Then pointer variable ptr will contain address of age which is "0x52436721"

#include <iostream>
using namespace std;
 
int main () {
   int  age = 10;
   int *ptr = &age;
 
   cout << "Value of count variable is " << age << endl;
   cout << "Address of count variable: " << ptr << endl;
   cout << "Value retrieved through pointer : " << *ptr;
 
   return 0;
}

Output
Value of count variable is 10
Address of count variable: 0x22fe34
Value retrieved through pointer : 10

Size Of Pointer Variable

The size of a pointer variable depends on system architecture. A memory address is considered as integer value. Size of a pointer is fixed, it doesn't depend on the data type it is pointing to. We can use size of operator to get the size of a pointer.

C++ Program to print the size of pointer
// C++ Program to print the size of pointer variables 

#include <iostream>
using namespace std;
 
int main() {
    int count = 10;
    float sum = 20.5;
    int *null_ptr = NULL;
    int *int_ptr = &count;
    float *float_ptr = &sum;
     
    cout << "Size of NULL Pointer : " << sizeof(null_ptr) << " Bytes\n"; 
    cout << "Size of Integer Variable : " << sizeof(count) << " Bytes\n"; 
    cout << "Size of Integer Pointer : " << sizeof(int_ptr) << " Bytes\n"; 
    cout << "Size of Float Variable : " << sizeof(sum) << " Bytes\n"; 
    cout << "Size of Float Pointer : "  << sizeof(float_ptr) << " Bytes\n"; 
    
    return 0;
}

Output
Size of NULL Pointer : 8
Size of Integer Variable : 4
Size of Integer Pointer : 8
Size of Float Variable : 4
Size of Float Pointer : 8

Passing Pointer to Function in C++

C++ programming language allows us to pass pointer to a function as argument. We can pass the address of the variable to the formal arguments of a function. This way of calling a function by passing pointer arguments is known as call by reference.

Any change in the value of formal parameters inside function's body will affect the value of actual parameter because both are pointing to same memory location.

To pass a pointer to a function, we have to declare the function argument of pointer type.


Different ways of declaring function which takes an array as input

Function argument as a pointer to the data type of array.
int testFunction(int *array){
 // Function body
}
By specifying size of an array in function parameters.
int testFunction(int array[10]){
// Function body
}
By passing unsized array in function parameters.
int testFunction(int array[]){
// Function body 
}

C++ program to pass pointer to a function

#include <iostream>
using namespace std;
   
void getDoubleValue(int *ptr){
   *ptr = (*ptr) * 2;
   cout << "F(Formal Parameter) = " << *ptr << endl;
}
  
int main(){
   int A;
   cout << "Enter a number\n";
   cin >> A;
   // Calling function by passing address of A
   getDoubleValue(&A);
   /* Any change in the value of formal parameter(F)
   will effect the value of actual parameter(A) */
   cout << "A(Actual Parameter) = " << A;
   
   return 0;
}

Output
Enter a number
23
F(Formal Parameter) = 46
A(Actual Parameter) = 46

Not only single variables, we can pass pointer to a array, structures, objects and user defined data types also. Here is an example of passing an array to a function in C++.


C++ program to pass an array to a function

#include <iostream>
using namespace std;
 
// This function takes integer pointer as argument
void printArrayOne(int *array, int size){
    int i;
    for(i=0; i<size; i++){
        cout << array[i] << " ";
    }
    cout << endl;
}
 
int main(){
   int score[5]={1, 2, 3, 4, 5};
   // Passing name of array 
   printArrayOne(score, 5);
    
   return 0;
}

Output
1 2 3 4 5

Returning Pointer from Function in C++

In C++ programming language, we can return a pointer from a function like any other data type. We have to declare return type of the function as pointer.

For Example :
int* getEvenNumbers(int N){
/* Function Body */
}
Points to Remember
As we know that, local variables gets created when control enters a function and gets destroyed as soon as control exits from a function. We should not return pointer to a local variable because as soon as control returns from a function the memory pointed by pointer no longer contains data of local variable.

If we want to return pointer to a local variable then we should declare it as a static variable so that it retains it's value after control exits from function.

C++ Program to return a pointer from a function

#include <iostream>
using namespace std;
  
// This function returns an array of N odd numbers
int* getOddNumbers(int N){
    // Declaration of a static local integer array 
    static int oddNumberArray[100];
    int i, odd = 1;
      
    for(i=0; i<N; i++){
        oddNumberArray[i] = odd;
        odd += 2;
    }
    // Returning base address of oddNumberArray array
    // As oddNumberArray is a static variable, it will 
    // retain it's value even after function exits 
    return oddNumberArray;
}
  
int main(){
   int *array, counter;
   
   array = getOddNumbers(10);
   cout << "Odd Numbers\n";
    
   for(counter=0; counter<10; counter++){
       cout << array[counter] << " ";
   }

   return 0;
} 

Output
Odd Numbers
1 3 5 7 9 11 13 15 17 19

Best Practices for Using Pointers in C++

  • Initialize Pointers : Always initialize pointers before using them to avoid undefined behavior.
    // Uninitialized pointer (may point to any memory location)
    int* uninitializedPointer; 
    // Initialized pointer (points to nothing initially)
    int* initializedPointer = nullptr; 
    

  • Avoid Wild Pointers : Avoid using pointers that haven't been assigned a valid memory address to prevent undefined behavior.
    // Avoid using wild pointers
    int* wildPointer; 
    // Now it's assigned a valid memory address
    wildPointer = new int; 
    

  • Check for Null Pointers : Before dereferencing pointers, check if they are null to avoid runtime errors.
    int* possiblyNullPointer = nullptr;
    
    if (possiblyNullPointer != nullptr) {
        // Dereference the pointer safely
        int value = *possiblyNullPointer;
    }
    

  • Free Dynamically Allocated Memory : Always free dynamically allocated memory using delete or delete[] to prevent memory leaks.
    int* dynamicNumber = new int;
    // Perform operations with dynamicNumber
    // Free the allocated memory
    delete dynamicNumber;