Pointers in C

Pointers:

A pointer is a variable that stores the address of another variable. Pointers in C can have any name which is legal for the other variables.

Pointers can be declared in the declarative part of the program.

Pointer declaration: 

The syntax of declaring the Pointer is 

data type * variable name;

Ex: int * P;

where * denotes the indirection operator or dereferenced operator or value at the address operator.

Initializing the Pointer variable:

Once we have declared the pointer variable and if we have to use the pointer variable in our program then we have to initialize the pointer. 

The uninitialized pointers will produce errors in the results.

Ex: int a=10, *P;

P=&a;

C program to display the value and address of the variable using Pointers.

#include <stdio.h>
int main() {
    // Declare a variable of your chosen data type
    int num = 42; // You can change this value
    // Declare a pointer variable to hold the address of 'num'
    int *ptr; 
    // Assign the address of 'num' to the pointer 'ptr'
    ptr = &num; // The & operator gets the address of a variable
    // Display the value of 'num' using the variable itself
    printf("Value of num: %d\n", num);
    // Display the value of 'num' using the pointer (dereferencing)
    printf("Value of num using pointer: %d\n", *ptr); // *ptr dereferences the pointer
    // Display the address of 'num' using the & operator
    printf("Address of num: %p\n", &num);  
    // Display the address of 'num' using the pointer variable
    printf("Address of num using pointer: %p\n", ptr); 
    
    return 0;
}

Output:

Value of num: 42
Value of num using pointer: 42
Address of num: 0x7ffe7554dcbc
Address of num using pointer: 0x7ffe7554dcbc

Pointer Increment/decrement operators:

In C language it is possible to add or subtract the integers from pointers. When we increment a pointer value, the value is increased by the size of its data type.

When we decrement a pointer value, the value is decreased by the size of its data type.

Int a=10, *P;
P=&a;
Printf(“the address of a is %u\n”,P); 🡪 2030
P = P+1;
Printf(“the address of a is %u\n”,P); 🡪 2032
Printf(“the address of a is %u\n”,P++); 🡪 2032
Printf(“the address of a is %u\n”,++P); 🡪 2036
P=P+2;
Printf(“the address of a is %u\n”,P); 🡪 2040
P=P-1;

In C language the following operations are invalid or illegal. They are

P1+P2, P1*P2, P1/P2 but we can perform subtraction of two pointers P1-P2.

Pointers can also be compared by using relational operators such as P1>P2 and P1>=P2, P1<P2, P1<=P2, P1==P2, P1!=P2.

Pointer to Pointer:

A pointer to pointer is a variable that contains the address of another pointer variable. It is denoted by **.

Null Pointer: 

A pointer is set to be a null pointer when its right value is zero or null. A null pointer can never point to valid data.

Ex: int *P=0; or int*P=NULL;

Void Pointers: 

Pointers can also be declared as void data types. Void pointers cannot be dereferenced without an explicit type of conversion. 

This is because being void the compiler cannot determine the size of the object that the pointer points to void pointers. Void pointers are also called generic pointers.

Void pointers can be converted into any basic data type pointer.

The syntax is

(data type*) Pointer Variable;

Ex: (int*)P;  

(float*)P;

Pointers using Arrays:

An array is a collection of similar data items that are stored under a common name. 

When we declare an array the consecutive memory locations are allocated to the array elements. Elements of an array can be effectively assessed by using pointers.

An array itself is a pointer which always points to the first element of the array. Initialization of a pointer to an array can be done by P=&a[0]; or P=a.

The array elements can be accessed by using a pointer variable such as P[i] or *(P+i).

We can also access the array elements without pointers such as a[i] or *(a+i).

Pointers using 2-D arrays:

Pointers can also be used in 2-D arrays. A pointer to 2-D array can be declared as datatype(pointer variable)[size];

Ex: int(*a)[10];

Array of pointers:

C language supports an array of pointers. A collection of pointers which are stored under a common name is called an array of pointers. 

In this array we store the address of different variables of similar data type.

The syntax is 

datatype * array name[size]; 

where size specifies the maximum number of addresses which we can store.

Ex: int *P[3];

Pointers using Strings:

A string is a sequence of characters that are enclosed within double quotation marks. 

A string can be easily represented by using a one-dimensional character array. 

We can also use pointers to access the strings.

C Program to accept the string and display it by using pointers.

#include <stdio.h>
int main() {
    // Declare a character array to store the string
    char str[100];  // You can adjust the size as needed
    // Declare a character pointer
    char *ptr;
    // Prompt the user to enter a string
    printf("Enter a string: ");
    // Read the string from the user (including spaces)
    scanf("%[^\n]s", str); 
    // Initialize the pointer to the beginning of the string
    ptr = str;
    // Display the string using the pointer
    printf("Entered string is: ");
    while (*ptr != '\0') { // Iterate until the null terminator is reached
        printf("%c", *ptr); // Print the character pointed to by 'ptr'
        ptr++;             // Move the pointer to the next character
    }
    printf("\n"); 
    return 0;
}

Output:

Enter a string: graduate
Entered string is: graduate

Passing arrays as a Parameter to a function:

In order to pass 1-D array as a parameter to the function it is declared as

Return datatype function name(datatype array name[], datatype variable1, datatype variable 2,….);

Passing 1-D array as a parameter to a function with the help of pointer, the syntax is 

Return datatype function name(datatype function name, datatype variable1, datatype variable 2,….);

Passing 2-D arrays to function:

The syntax is

Return datatype function name(datatype array name[size1][size2], datatype variable1, datatype variable 2,….);

Passing 2-D array as a parameter to a function using pointer:

The syntax is

Return datatype function name datatype (*variable name[size], datatype variable1, datatype variable 2,….);

Passing ordinary variable addresses as parameters to function:

The process of calling a function using pointers is to pass the address of the variables. This mechanism is called as call by reference.

The calling function will send the address of the variables as actual parameters.

The formal parameters will be the pointers to the actual parameters.

Functions returning a Pointer:

Functions can also return a pointer data type. To return a pointer from sub function to the main function it can be declared as 

Return datatype * function name (parameter list);

Advantages of Pointers in C:

  1. Pointers save memory space.
  2. Execution time with the pointer is faster because data is manipulated with the address. The memory is effectively used with the help of pointers.
  3. Pointers are used for dynamic memory allocation.
  4. Pointers are effectively used in data structures.
  5. Pointers are effectively used for retrying the data either from 2D or Multi-dimensional arrays.
  6. Pointers reduce the length and complexity of the programme.
  7. Pointers can be used to provide clarity and simplicity.

Disadvantages of Pointers in C:

  1. Memory Errors: The Silent Threat
  • Segmentation Faults: Incorrect pointer usage can trigger dreaded segmentation faults, crashing your program when it tries to access invalid memory.
  • Memory Leaks: Forgetting to free dynamically allocated memory can lead to memory leaks, gradually consuming system resources and potentially causing instability.
  1. Dangling Pointers: The Unpredictable Danger
  • Undefined Behavior: Dangling pointers, which point to freed memory, can lead to unexpected program crashes or data corruption due to their unpredictable nature.
  1. Complexity & Bugs: A Delicate Balance
  • Steeper Learning Curve: Pointers add complexity to C programming. Misunderstanding their nuances can easily introduce bugs into your code.
  • Debugging Nightmares: Pointer-related errors can be notoriously difficult to diagnose and fix, as their symptoms may not be immediately obvious.
  1. Security Risks: The Hacker’s Playground
  • Buffer Overflows: Pointers can be exploited to overwrite memory beyond the intended boundaries, leading to buffer overflows.
  • This is a major security vulnerability that can be used to inject malicious code.
  1. Performance Overhead (Situational): The Hidden Cost
  • Indirect Access: While pointers can be efficient, accessing data through them involves an extra level of indirection compared to using variables directly. 
  • This might introduce a slight performance overhead in specific, highly optimized scenarios.

Conclusion:

Pointers in C are a double-edged sword: powerful but demanding. They offer efficient memory manipulation, streamlined data structure handling, and dynamic memory allocation. However, misuse can lead to crashes, memory leaks, security vulnerabilities, and challenging debugging. Understanding their nuances and employing best practices is crucial for successful C programming.

FAQs of Pointers in C 

1. What is a pointer in C, and how does it work?

  • A pointer is a variable that stores the memory address of another variable. It acts like a signpost, directing you to the location where the actual data resides. You can then use the pointer to manipulate or access that data indirectly.

2. Why do we use pointers in C?

  • Pointers offer several advantages:
    • Dynamic memory allocation: Pointers allow you to allocate memory during program execution, making your code more flexible.
    • Efficient data manipulation: You can pass pointers to functions, enabling them to modify the original data without creating copies.
    • Data structures: Pointers are essential for building complex data structures like linked lists, trees, and graphs.
    • Function pointers: Pointers to functions provide a way to create callbacks and implement dynamic dispatch.

3. What is the difference between a pointer and a reference in C?

  • C doesn’t have references like C++, but it’s a common question due to similarities. Here’s the key difference:
    • Pointers: Can be null, can be reassigned to point to different variables, and can perform pointer arithmetic.
    • References (in C++): Must be initialized and cannot be null, cannot be reassigned, and have the same syntax as regular variables.

4. How do I avoid common pointer errors like segmentation faults and memory leaks?

  • Segmentation Faults: Always initialize pointers before using them, and check if a pointer is null before dereferencing it.
  • Memory Leaks: Deallocate dynamically allocated memory using free() when you’re done with it.

5. What are some best practices for using pointers in C?

  • Clarity: Use meaningful names for pointers to make your code more readable.
  • Comments: Add comments to explain complex pointer operations.
  • Initialization: Always initialize pointers to NULL or a valid address.
  • Error Handling: Include checks for null pointers before dereferencing.
  • Const Correctness: Use const to indicate when a pointer shouldn’t modify the data it points to.
  • Memory Management: Be diligent about deallocating dynamically allocated memory.

Scroll to Top