Open In App

Types of Pointer in Programming

Last Updated : 02 May, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

Pointers in programming are variables that store the memory address of another variable. There are several types of pointers, including Null pointer, Void pointer, Wild pointer, Dangling pointer, Complex pointer, Near pointer, Far pointer, and Huge pointer. Each type has its characteristics and uses, providing flexibility and efficiency in memory management.

What is a Pointer?

A variable that store­s another variable’s memory addre­ss is called a pointer. Normal variables store­ values. But pointers hold memory locations whe­re values are ke­pt. Using pointers lets you access and change­ system memory directly. This can make­ programs more efficient and powe­rful. C and C++ use pointers a lot. But other language­s can also have pointers, though maybe not the­ same.

Types of Pointers in Programming:

There are several types of pointers used in programming, each serving different purposes:

1. Basic Pointer:

A primary pointer is a variable that is a memory address of another variable. Instead of having the data itself physically present, pointers only connect to the memory location where the data is kept. Answering that, the program will get a chance to use it to read and write with the value located at the given memory address.

Below is the implementation of the above idea:

C++
#include <iostream>
using namespace std;

int main()
{
    // Declare an integer variable
    int var = 23;
    // Declare a pointer to an integer
    int* ptr;
    // Assign the pointer the address of var
    ptr = &var;

    cout << "Value of var: " << var << endl;
    cout << "Address of var: " << &var << endl;
    cout << "Value of ptr (Address it holds): " << ptr
         << endl;
    cout << "Value pointed to by ptr: " << *ptr
         << endl; // Dereferencing pointer to access the
                  // value of var

    return 0;
}
C
#include <stdio.h>

int main()
{
    int var = 23;

    // Declare a pointer to an integer
    int* ptr;

    // Assign the pointer the address of var
    ptr = &var;

    // Output the value of var
    printf("Value of var: %d\n", var);

    // Output the memory address of var
    printf("Address of var: %p\n", &var);

    // Output the address stored in ptr
    printf("Value of ptr (Address it holds): %p\n", ptr);

    // Output the value at the memory address stored in ptr
    printf("Value pointed to by ptr: %d\n", *ptr);

    return 0;
}

Output
Value of var: 23
Address of var: 0x7ffc833c13b4
Value of ptr (Address it holds): 0x7ffc833c13b4
Value pointed to by ptr: 23

2. Null Pointer:

Null pointer is a specific component of pointers which doesn’t point to any legitimate memory location. It is applied in programming to denote the particular case when a pointer intentionally not points on an object and is uninitialized. Such a pointer absolutely literally refers to the value 0 (or NULL, which in C terminology is generally set to 0, and nullptr in C++), which denotes a protected value reserved by the language rules that does not refer to anything.

Below is the implementation of the above idea:

C++
#include <iostream>
using namespace std;

int main() {
    int *ptr = nullptr;  // Preferred over NULL in C++

    if (ptr == nullptr) {
      cout << "The pointer is null." << endl;
    }

    return 0;
}
C
#include <stdio.h>

int main() {
    int *ptr = NULL;  // Declaration of a null pointer

    if (ptr == NULL) {
        printf("The pointer is null.\n");
    }

    return 0;
}
Java
public class Main {
    public static void main(String[] args) {
        Integer num = null;  // Java uses null to denote the absence of a value.

        if (num == null) {
            System.out.println("The variable is null.");
        }
    }
}
Python
num = None  # Python's equivalent to null pointers in other languages

if num is None:
    print("The variable is None.")
JavaScript
// In JavaScript, we use 'let' to declare variables
let ptr = null;  

// 'if' statement is used to check if the pointer is null
if (ptr === null) {
  // 'console.log' is used in JavaScript for printing
  console.log("The pointer is null.");
}

Output
The pointer is null.

3. Pointer to Pointer (Double Pointer):

Pointer to a pointer sometimes gets referred as a double pointer. It is a type of pointer which stores the memory address of another pointer. Double pointers are used to achieve indirect reference of data via another pointer in the case of its required. As an important point, this C-like languages features support multiple indirection that can be used as extra layers to direct data structures which are the most useful for the dynamic data structures.

Below is the implementation of the above idea:

C++
//Passing Pointers to Functions

#include <iostream>
using namespace std;

void allocateArray(int** &ptr, int size) {
    ptr = new int*[size]; // Allocate array of pointers
    for (int i = 0; i < size; i++) {
        ptr[i] = new int[size]; // Allocate int array for each pointer
    }

    // Initialize array elements
    int value = 1;
    for (int i = 0; i < size; i++) {
        for (int j = 0; j < size; j++) {
            ptr[i][j] = value++;
        }
    }
}

void freeArray(int** &ptr, int size) {
    for (int i = 0; i < size; i++) {
        delete[] ptr[i]; // Free each sub-array
    }
    delete[] ptr; // Free the top-level array
    ptr = nullptr; // Safeguard pointer
}

int main() {
    int **arr = nullptr;
    int size = 3;

    allocateArray(arr, size);

    // Output the array
    for (int i = 0; i < size; i++) {
        for (int j = 0; j < size; j++) {
            cout << arr[i][j] << " ";
        }
        cout << endl;
    }

    freeArray(arr, size);

    return 0;
}
C
//Dynamic 2D Array to show working of Double pointers in C.

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

int main() {
    int **arr; // Declare a double pointer
    int rows = 3;
    int cols = 4;
    int i, j, count = 0;

    // Step 1: Allocate memory for 'rows' pointers
    arr = (int **)malloc(rows * sizeof(int *));
    if (arr == NULL) {
        fprintf(stderr, "Out of memory\n");
        exit(1);
    }

    // Step 2: Allocate memory for each row
    for (i = 0; i < rows; i++) {
        arr[i] = (int *)malloc(cols * sizeof(int));
        if (arr[i] == NULL) {
            fprintf(stderr, "Out of memory\n");
            exit(1);
        }
    }

    // Step 3: Assign values to allocated memory
    for (i = 0; i < rows; i++) {
        for (j = 0; j < cols; j++) {
            arr[i][j] = ++count;  // Or any other value
        }
    }

    // Step 4: Output the array
    for (i = 0; i < rows; i++) {
        for (j = 0; j < cols; j++) {
            printf("%d ", arr[i][j]);
        }
        printf("\n");
    }

    // Step 5: Free the allocated memory
    for (i = 0; i < rows; i++) {
        free(arr[i]);
    }
    free(arr);

    return 0;
}

Output
1 2 3 
4 5 6 
7 8 9 

4. Smart Pointers:

Smart pointers are advanced cursor varieties provided by C++ to look after the memory of the dynamically allocated objects. They are STL(C++ Standard Library) generic classes that contain a plain pointer and ensure the code is not brought up in memory leaks and dangling pointers and, therefore, is clean and elegant. Smart pointers act as automatic memory deallocators, simulating the works of regular pointer with additional logics to manage lifecycle and resources, but eventually introduce a safer approach to overcome the problem mentioned with using traditional raw pointers.

Below is the implementation of the above idea:

C++
#include <iostream>
#include <memory> // Include for smart pointers
using namespace std;

int main()
{
    // Using std::unique_ptr
    unique_ptr<int> uPtr(new int(10));
    cout << "uPtr = " << *uPtr << endl;

    // Transferring ownership
    unique_ptr<int> uPtr2 = move(uPtr);
    if (!uPtr)
        std::cout << "uPtr is empty\n";

    // Using std::shared_ptr
    shared_ptr<int> sPtr(new int(20));
    shared_ptr<int> sPtr2 = sPtr; // Both now own the memory
    cout << "sPtr = " << *sPtr << ", sPtr2 = " << *sPtr2
         << endl;
    cout << "sPtr use_count = " << sPtr.use_count() << endl;

    // Using std::weak_ptr
    weak_ptr<int> wPtr(
        sPtr); // Does not increase reference count
    shared_ptr<int> sPtr3
        = wPtr.lock(); // Creates a shared_ptr from weak_ptr
    if (sPtr3)
        cout << "sPtr3 = " << *sPtr3 << endl;

    return 0;
}

Output
uPtr = 10
uPtr is empty
sPtr = 20, sPtr2 = 20
sPtr use_count = 2
sPtr3 = 20

5. Void Pointers:

A void pointer in programming is a special type of pointer that doesn’t have an associated data type. It can hold the address of any type of data and can be typecasted to any type. This makes it a versatile tool, often referred to as a “generic pointer” or “wildcard pointer“, used in various programming scenarios for flexibility and efficiency.

  • Void Pointers can hold the address of a data type of integer, a float or a string, even to structured data.
  • Does not figure out which type of object it is pointing at and thus is unable to be directly deference.
  • A reference to it needs to be casted as another pointer type before it can be dereferenced.
  • Generally available in C for dynamic memory allocation, interfacing with the hardware, implementing polymorphic functions, and handling the data in the constructs which are agnostic to the data types.

Below is the implementation of the above idea:

C++
#include <iostream>
using namespace std;

int main() {
    int a = 10;
    float b = 3.14;
    void *p = nullptr;  // using nullptr which is type-safe in C++

    p = &a;
    cout << "Integer value: " << *(static_cast<int*>(p)) << endl;  // using static_cast for type safety

    p = &b;
    cout << "Float value: " << *(static_cast<float*>(p)) << endl;

    return 0;
}
C
#include <stdio.h>
#include <stdlib.h>

int main() {
    int a = 10;
    float b = 3.14;
    void *p = NULL;  // void pointer declaration

    p = &a;  // storing address of int
    printf("Integer value: %d\n", *(int *)p);  // type casting to int pointer and dereferencing

    p = &b;  // storing address of float
    printf("Float value: %f\n", *(float *)p);  // type casting to float pointer and dereferencing

    return 0;
}

Output
Integer value: 10
Float value: 3.14

6. Integer Pointer:

Integer pointer is a kind of pointer that when it points it does so specifically to integer. Pointers stores the RAM address of another variable while they are the variables themselves. In the case of pointers to integers the address or the place that the value of integer is located will be implicated.

Below is the implementation of the above idea:

C++
#include <iostream>
using namespace std;

int main() {
    int val = 10;
    int* ptr = &val;

    cout << "Value of val: " << val << endl;
    cout << "Address of val: " << &val << endl;
    cout << "Value of ptr: " << ptr << endl;
    cout << "Value pointed to by ptr: " << *ptr << endl;

    return 0;
}
C
#include <stdio.h>

int main() {
    int val = 10;
    int *ptr = &val;  // Pointer to an integer variable

    printf("Value of val: %d\n", val);  // Output the value of val
    printf("Address of val: %p\n", (void *)&val);  // Output the memory address of val
    printf("Value of ptr: %p\n", (void *)ptr);  // Output the memory address stored in ptr
    printf("Value pointed to by ptr: %d\n", *ptr);  // Output the value at the memory address stored in ptr

    return 0;
}

Output
Value of val: 10
Address of val: 0x7ffe482d9c74
Value of ptr: 0x7ffe482d9c74
Value pointed to by ptr: 10

7. Float Pointer:

A float pointer is a pointer that specifically refers to the address of a floating-point data type. The floating-point data type usually represents real numbers (numbers with fractional parts) in the way that a single representation can accommodate a large range of values. The pointer keeps the memory address where the first byte of the float data type is remained. Pointers, in general, are applicable for efficient accessing of arrays and other data structures, dynamic memory administration and handling polymorphism in object-oriented programming language. Procedural languages that have float pointers.

Below is the implementation of the above idea:

C
#include <stdio.h>

int main() {
    float number = 10.5;
    float* ptr = &number;  // Pointer to a float

    printf("Value of number: %f\n", number);
    printf("Address of number: %p\n", (void*)&number);
    printf("Value of ptr (address it points to): %p\n", (void*)ptr);
    printf("Value at address stored in ptr: %f\n", *ptr);

    return 0;
}

Output
Value of number: 10.500000
Address of number: 0x7fff573317ec
Value of ptr (address it points to): 0x7fff573317ec
Value at address stored in ptr: 10.500000

8. Array Pointers:

An array pointer is a kind of pointer that can be used to point to the first element of the associated array in the memory. Such a pointer, besides storing the memory address of the fist element of the array, is also usually tied to the element type of the array. The pointer will become aware of this and will facilitate pointer arithmetic making it possible to either increase it or decrease it and move through the array.

Array pointer can be defined as:

  • A pointer that indicates the location of the first item of an array.
  • It is applicable for random access of the array elements by using the pointer instead of the array indices.

Below is the implementation of the above idea:

C
#include <stdio.h>

int main() {
    int arr[] = {10, 20, 30, 40, 50};
    int* p = arr; // Array pointer to the first element of arr

    for(int i = 0; i < 5; i++) {
        printf("%d ", *(p + i));  // Accessing array elements through pointer arithmetic
    }

    return 0;
}
C#
using System;

class Program {
    static unsafe void Main() {
        int[] arr = {10, 20, 30, 40, 50};
        fixed (int* p = arr) {
            for(int i = 0; i < arr.Length; i++) {
                Console.WriteLine(*(p + i));  // Pointer arithmetic to navigate through the array
            }
        }
    }
}

Output
10 20 30 40 50 

9. Function Pointer:

Function pointers are very powerful programming tools using which programmers can save function references that can be later called. It is the feature that is most visible for callback functions, implementing plugins, or for the simulation of polymorphism in C-like languages. Here is a short description of function pointers and their use in the several programming languages that allow this functionality.

Below is the implementation of the above idea:

C++
#include <iostream>
using namespace std;

class Base {
public:
    void say_hello() const { cout << "Hello, World!\n"; }
};

int main() {
    void (Base::*func_ptr)() const = &Base::say_hello;
    Base obj;
    (obj.*func_ptr)();  // Calling member function using function pointer
    return 0;
}
C
#include <stdio.h>

void hello() {
    printf("Hello, World!\n");
}

void goodbye() {
    printf("Goodbye, World!\n");
}

int main() {
    void (*func_ptr)();  // Declaration of a function pointer
    func_ptr = hello;    // Pointing to hello function
    func_ptr();          // Calling hello function
    func_ptr = goodbye;  // Now pointing to goodbye function
    func_ptr();          // Calling goodbye function
    return 0;
}
C#
using System;

public delegate void GreetingDelegate();

public class Program {
    public static void SayHello() {
        Console.WriteLine("Hello, World!");
    }

    public static void Main() {
        GreetingDelegate del = new GreetingDelegate(SayHello);
        del();
    }
}

Output
Hello, World!

10. Pointer to Structure (Struct Pointer):

A Pointer to Structure (or Struct Pointer) is a concept present in some programming languages C and C++. This construct enables a creation of pointers purposely directed to structures. Different from Structures, these structures are user-specified data types that permit the combination of different items of data. Pointer to structures are especially important for dynamic allocation of memory, function parameters passed to big structures with less overhead, and data structures which include linked lists and trees.

A struct pointer in programming is a type of pointer that remembers the address of a structure. The struct pointer is used instead of the usual numeric data type. It refers to a struct data type which is user-defined.

Below is the implementation of the above idea:

C++
#include <iostream>
#include <cstring>
using namespace std;

struct Employee {
    int id;
    char name[20];
};

int main() {
    Employee *ptr = new Employee;  // Dynamically allocate memory for one Employee struct

    // Access struct members through pointer
    ptr->id = 123;
    strcpy(ptr->name, "Geeks For Geeks");

    cout << "Employee ID: " << ptr->id << endl;
    cout << "Employee Name: " << ptr->name << endl;

    delete ptr;  // Free the allocated memory
    return 0;
}
C
#include <stdio.h>
#include <stdlib.h>

typedef struct {
    int id;
    char name[20];
} Employee;

int main() {
    Employee *ptr = malloc(sizeof(Employee));  // Dynamically allocate memory for one Employee struct
    if (ptr == NULL) {
        fprintf(stderr, "Malloc failed\n");
        return -1;
    }

    // Accessing struct members through pointer using arrow operator
    ptr->id = 123;
    strcpy(ptr->name, "Geeks For Geeks");

    printf("Employee ID: %d\n", ptr->id);
    printf("Employee Name: %s\n", ptr->name);

    free(ptr);  // Free the allocated memory
    return 0;
}

Output
Employee ID: 123
Employee Name: Geeks For Geeks

Conclusion:

In conclusion, pointers in programming are powerful tools that hold memory addresses of variables. Different types of pointers like Null, Void, Wild, Dangling, Complex, Near, Far, and Huge pointers each have unique properties and uses. They play a crucial role in memory management, making programs more efficient and flexible.



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads