
What are Pointers in C?
Pointers in C are variables that store memory addresses. They are used to manipulate data indirectly by accessing and modifying the memory locations that they point to. Pointers provide flexibility and efficiency in programming, allowing functions to modify variables outside their scope, dynamically allocate memory, and work with complex data structures.
In C, the * and & symbols have special meanings when used with pointers.
1. The * Operator:
Declaration: When declaring a pointer variable, the * is used to indicate that the variable is a pointer. For example:
int *ptr; // Declare a pointer to an integerDereferencing: The * operator is also used to dereference a pointer, which means accessing the value stored at the memory address pointed to by the pointer. For example:
int num = 10;
int *ptr = # // Assign the address of num to ptr
int value = *ptr; // Dereference the pointer to get the value2. The & Operator:
The & operator is used to obtain the memory address of a variable. It returns the address where the variable is stored in memory. For example:
int num = 10;
int *ptr = # // Assign the address of num to ptr using the & operatorIn the above example, &num returns the memory address of the variable num, and it is assigned to the pointer ptr. This allows ptr to “point” to the memory location of num.
Example of Pointer:
#include <stdio.h>
int main() {
int num = 10;
int *ptr = #
printf("Value of num: %d\n", num);
printf("Value stored in ptr: %p\n", ptr);
printf("Value pointed by ptr: %d\n", *ptr);
return 0;
}Output:
Value of num: 10
Value stored in ptr: 0x7fff5251701c
Value pointed by ptr: 10Explanation:
- We declare an integer variable
numand initialize it with the value 10. - Then, we declare a pointer
ptrof typeint *(integer pointer) and assign it the address ofnumusing the&operator. - The first
printfstatement displays the value ofnum. - The second
printfstatement displays the value stored inptr, which is the memory address ofnum. - The third
printfstatement uses the*operator to access the value pointed byptr, which is the value ofnum.
1. Pointer to Array:
A pointer to an array in C holds the memory address of the first element of the array. Let’s consider an example:
#include <stdio.h>
int main() {
int arr[3] = {10, 20, 30};
int *ptr = arr;
printf("First element of arr: %d\n", *ptr);
printf("Second element of arr: %d\n", *(ptr + 1));
printf("Third element of arr: %d\n", *(ptr + 2));
return 0;
}Output:
First element of arr: 10
Second element of arr: 20
Third element of arr: 30Explanation
- We declare an integer array
arrwith three elements and initialize it with values. - Then, we declare a pointer
ptrof typeint *and assign it the address of the first element ofarr. - The first
printfstatement uses the*operator to access the value of the first element ofarrusing the pointerptr. - The second and third
printfstatements demonstrate how to access the second and third elements ofarrusing pointer arithmetic.
2. Pointer to Function:
A pointer to a function in C holds the memory address of a function. It allows us to call the function indirectly through the pointer. Here’s an example:
#include <stdio.h>
void hello() {
printf("Hello, world!\n");
}
int main() {
void (*ptr)() = hello;
printf("Calling the function through the pointer:\n");
ptr();
return 0;
}Output:
Calling the function through the pointer:
Hello, world!Explanation
- We define a function
hellothat prints “Hello, world!” to the console. - In the
mainfunction, we declare a function pointerptrusing the syntaxvoid (*ptr)(), which represents a pointer to a function that takes no arguments and returns void. - We assign the address of the
hellofunction to the pointerptr. - The
printfstatement demonstrates how to call the function indirectly through the function pointerptr.
3. Pointer to Structure:
A pointer to a structure in C holds the memory address of a structure. It allows efficient manipulation of structure members using pointers. Here’s an example:
#include <stdio.h>
struct Person {
char name[20];
int age;
};
int main() {
struct Person person;
struct Person *ptr = &person;
strcpy(ptr->name, "ANGRY BULBASAUR");
ptr->age = 25;
printf("Name: %s\n", ptr->name);
printf("Age: %d\n", ptr->age);
return 0;
}Output:
Name: ANGRY BULBASAUR
Age: 25Explanation
- We define a structure named
Personwith two members:name(an array of characters) andage(an integer). - In the
mainfunction, we declare a structure variablepersonand a pointer to the structureptr. - We assign the address of the
personstructure to the pointerptrusing the&operator. - The
strcpyfunction is used to copy the string “John” to thenamemember of the structure through the pointer. - We assign the value 25 to the
agemember of the structure through the pointer. - The
printfstatements display the values of the structure members accessed through the pointer.
More Examples of Pointer:
1. Swapping Value
#include <stdio.h>
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
int main() {
int x = 10, y = 20;
printf("Before swap: x = %d, y = %d\n", x, y);
swap(&x, &y);
printf("After swap: x = %d, y = %d\n", x, y);
return 0;
}Output:
Before swap: x = 10, y = 20
After swap: x = 20, y = 10Explanation:
- In this example, we define a function
swapthat takes two integer pointers as parameters. - Inside the function, we use the pointers to swap the values of the variables they point to.
- In the
mainfunction, we declare two integer variablesxandyand display their initial values. - We call the
swapfunction, passing the addresses ofxandy. - After the swap, the values of
xandyare displayed again, showing that they have been exchanged.
2. Linked List Implementation:
This example demonstrates the implementation of a singly linked list using pointers in C. It involves dynamically allocating memory for each node and manipulating the list using pointers.
#include <stdio.h>
#include <stdlib.h>
struct Node {
int data;
struct Node* next;
};
void insert(struct Node** head, int value) {
struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
newNode->data = value;
newNode->next = *head;
*head = newNode;
}
void display(struct Node* head) {
struct Node* current = head;
while (current != NULL) {
printf("%d ", current->data);
current = current->next;
}
printf("\n");
}
int main() {
struct Node* head = NULL;
insert(&head, 10);
insert(&head, 20);
insert(&head, 30);
insert(&head, 40);
printf("Linked List: ");
display(head);
return 0;
}Output:
Linked List: 40 30 20 10Explanation:
- The program defines a structure called
Nodethat represents a node in the linked list. Each node contains an integerdataand a pointernextto the next node. - The
insertfunction is used to insert a new node at the beginning of the linked list. It allocates memory for a new node, sets its data value, and updates thenextpointer to point to the current head of the list. Finally, it updates the head pointer to point to the new node. - The
displayfunction is used to traverse the linked list and print the data values of each node. - In the
mainfunction, a pointerheadis initialized asNULLto represent an empty linked list. - Several nodes are inserted into the list using the
insertfunction. - The linked list is displayed using the
displayfunction.
Rules to follow while using Pointers in C:
- Initialize Pointers: Always initialize pointers before using them. Assign them a valid memory address, either by pointing to an existing variable or using memory allocation functions like
mallocorcalloc. - Avoid Dereferencing Null Pointers: Null pointers do not point to valid memory addresses. Avoid dereferencing null pointers, as it can lead to crashes or undefined behavior.
- Avoid Dereferencing Uninitialized Pointers: Dereferencing uninitialized pointers can also result in crashes or unpredictable behavior. Always initialize pointers before accessing the memory they point to.
- Match Pointer Type with the Variable Type: Ensure that the pointer type matches the type of the variable it is pointing to. Pointers have a specific type associated with them, which determines the size of the memory block they can access.
- Respect Memory Allocation and Deallocation: When using dynamic memory allocation functions like
malloc,calloc, orrealloc, make sure to deallocate the memory usingfreewhen it is no longer needed. Failing to do so can result in memory leaks. - Avoid Pointer Arithmetic Errors: Be cautious when performing pointer arithmetic. Adding or subtracting an integer to a pointer should be done carefully to ensure that it remains within the allocated memory range.
- Be Mindful of Lifetime and Scope: Pointers should not be used to access memory outside their valid lifetime or scope. Avoid accessing memory that has already been deallocated or memory belonging to other variables.
- Avoid Pointer Aliasing: Pointer aliasing refers to multiple pointers pointing to the same memory location. It can lead to unexpected behavior and should be avoided unless explicitly intended.