Pointers
A pointer is a variable that stores the memory address of another variable. In languages like C and C++, pointers are commonly used for dynamic memory management, arrays, and data structures.
Declaration and Initialization:
int a = 10;
int *p = &a; // p now points to a
Pointer Arithmetic
Pointer arithmetic allows you to navigate through memory addresses based on the type of data the pointer points to.
Incrementing a Pointer: When you increment a pointer, it moves to the next memory address based on the size of the type it points to.
//int pointers
int arr[] = {10, 20, 30};
int *p = arr; // p points to arr[0]
p++; // p now points to arr[1]
//char pointers
char str[] = "Hello";
char *p = str; // p points to the first character 'H'
printf("%c\n", *p); // Output: H
p++; // Increment the pointer to point to the next character
printf("%c\n", *p); // Output: e
p++; // Increment again
printf("%c\n", *p); // Output: l
Subtracting Pointers: If you subtract one pointer from another (of the same type), it returns the number of elements between them.
int *p1 = &arr[0];
int *p2 = &arr[2];
int diff = p2 - p1; // diff is 2
Common Pitfalls
Null Pointers: A null pointer does not point to any valid memory location. dereferencing a null pointer leads to undefined behavior.
int *p = NULL; // *p = 5; // This will cause a runtime error.
Dangling Pointers: A dangling pointer points to a memory location that has been freed or deallocated. This can happen after using free()
on dynamically allocated memory.
int *p = malloc(sizeof(int));
free(p);
// p is now a dangling pointer.
//to avoid the dangling pointer scenario
//case:1
int* ptr = (int*)malloc(sizeof(int));
*ptr = 42;
free(ptr); // Free the allocated memory
ptr = NULL; // Set the pointer to nullptr
if (ptr) { // Check if ptr is valid before dereferencing
std::cout << *ptr; // This won't execute
}
//case:2 Avoid Returning Pointers to Local Variables
int* createArray() {
int arr[10]; // Local variable
return arr; // Dangerous: arr will be destroyed after function returns
}
//Instead, allocate memory on the heap and then return:
int* createArray() {
int* arr = new int[10]; // Allocate on heap
return arr; // Safe to return
}
In C++, prefer using smart pointers (std::unique_ptr
, std::shared_ptr
) instead of raw pointers. Smart pointers automatically manage memory and prevent dangling pointers by ensuring that memory is freed when the pointer goes out of scope or is no longer needed.
also using standard containers like std::vector
or std::string
in C++ can help manage memory automatically, reducing the chances of dangling pointers.
Memory Leaks: A memory leak occurs when you allocate memory but forget to free it, leading to wasted memory resources. This is common in long-running applications.
int *p = malloc(sizeof(int));
// Do something with p
// free(p); // If you forget this, it's a memory leak.
//in cpp
int* ptr = new int; // Allocate memory
*ptr = 42;
// ... use ptr ...
delete ptr; // Free memory
//For arrays:
int* arr = new int[10]; // Allocate array
// ... use arr ...
delete[] arr; // Free memory
The new
operator for a single object constructs the object and returns a pointer to it. When you call delete
, it invokes the destructor (if any) and then frees the memory.
on the other hand new[]
operator allocates memory for an array and constructs each element. When you call delete[]
, it invokes the destructors for each element in the array (if applicable) and then frees the entire block of memory.
Subscribe to my newsletter
Read articles from Shashi Shekhar directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by