Pointer In C Programming Examples | Double Pointer & Use

A pointer is also a variable that stores the memory address of another variable. The pointer variable itself also contains the address of memory. Pointers cannot store direct values; they only store memory addresses of where values are located.

This is useful for various reasons, such as dynamic memory allocation, arrays, and functions. As we know compiler assigns a unique address to each variable in a program.

How Memory address is find Using Pointers in C

 Pointer Declaration and Initialization: Code Example 

Here’s a very simple example of pointer declaration and initialization in C

#include <stdio.h>
int main()
{
    int a = 20;
    int *ptr;      // pointer declaration
    ptr = &a;      // pointer initialization
    printf("Address of a: %p\n", &a);  // Output: a's address
    printf("Address of *ptr: %p\n", &(*ptr));  // Output: a's address
    printf("Value of ptr: %p\n", ptr);  // Output: a's address
    printf("Value of a: %d\n", a);  // Output: 20 (value of a)
    printf("Value of *ptr: %d\n", *ptr);  // Output: 20 (value at a's address)
    printf("Value of *&a: %d\n", *(&a));  // Output: 20 (same as above)
    printf("Address of ptr: %p\n", &ptr);  // Output: ptr's address
    return 0;
}

Output:

Address of a: 000000000061FE1C
Address of *ptr: 000000000061FE1C
Value of ptr: 000000000061FE1C
Value of a: 20
Value of *ptr: 20
Value of *&a: 20
Address of ptr: 000000000061FE10

Explanation: &var gives the address of var. *ptr giving you the value stored at that address.

Important:

Dereferencing a pointer means accessing the value stored at the memory address the pointer holds. dereferencing a pointer is done using the * operator.

Double Pointer (Pointer to Pointer)

In C, a pointer-to-pointer (or “double pointer”) allows us to store the address of another pointer. Here’s a simple example diagram

double pointers in programming

According to above diagram, var is an integer variable set to 20. ptr1 is a pointer variable that holds the address of var. ptr2 is a pointer-to-pointer variable that holds the address of ptr1.

Double Pointer Code Example

#include <stdio.h>
int main() {
    int var = 20;
    int *ptr1 = &var;   // Pointer to var
    int **ptr2 = &ptr1; // Pointer to ptr1
    printf("Value pointed to by ptr: %d\n", *ptr1); // Prints 20
    printf("Value pointed to by pptr: %d\n", **ptr2); // Prints 20
    return 0;
}

Output:

Value pointed to by ptr: 20
Value pointed to by pptr: 20

Use of Pointer

Pointers are very powerful and useful in programming, especially in languages like C and C++. Here are some key uses of pointers:

1. Dynamic Memory Allocation

Pointers are essential for managing memory dynamically. Functions like malloc, calloc, and free use pointers to allocate and deallocate memory.

Example:

int *ptr = (int*) malloc(sizeof(int) * 5);  // Allocates memory for 5 integers 

2. Efficient Array and String Handling

Pointers provide direct access to array elements and can optimize string manipulation, as arrays are essentially pointers to the first element.

Example:

int arr[] = {41, 25, 33, 41, 50};
int *ptr = arr;  // Pointer to the first element of the array
printf("%d \n", *(ptr)); // Dereferencing pointer (output 41)
printf("%d\n", *(ptr + 2));  // Access the third element: 33
// Accessing and printing each element using pointer
for (int i = 0; i < 5; i++) {
printf("%d ", *(ptr + i)); // Dereferencing pointer to access elements
}
printf("\n"); // Output: 41, 25, 33, 41, 50
return 0;
}

3. Function Arguments (Passing by Reference)

Pointers allow passing by reference, enabling functions to modify the original data, which is efficient in terms of memory and performance.

Example:

void updateValue(int *ptr) {
*ptr = 20; // Dereference and modify the original value
}
int main() {
int number = 10;
updateValue(&number); // Pass the address of 'number'
printf("%d", number); // Prints 20
return 0;
}

4. Building Data Structures (Linked Lists, Trees, Graphs)

Pointers are crucial for building complex data structures like linked lists, trees, and graphs, where each element points to others.

Example (Linked List):

struct Node {
    int data;
    struct Node *next;  // Pointer to the next node
};

5. Accessing Hardware and Memory Directly

In low-level programming (e.g., embedded systems), pointers can access hardware memory directly, useful for controlling hardware registers.

Example:

int *port = (int *) 0x4000;  // Pointer to a memory-mapped register
*port = 1;  // Set the register value to 1

6. Pointer Arithmetic

Pointers allow arithmetic operations (like incrementing or decrementing) to traverse arrays or other memory blocks efficiently.

Example:

int arr[] = {1, 2, 3, 4};
int *ptr = arr;
printf("%d\n", *(ptr + 1));  // Prints 2, accessing the second element

7. Pointers to Functions

Function pointers allow you to store addresses of functions, enabling callback mechanisms and flexible programming patterns.

Example:

void printMessage() {
    printf("Hello, world!\n");
}
int main() {
    void (*funcPtr)() = printMessage;  // Pointer to 'printMessage'
    funcPtr();  // Calls 'printMessage' via the pointer
    return 0;
}