Introduction

Pointers are variables that store the location of some other variable in memory. They basically point to the memory location where the original variable is stored. This property allows us to manipulate the variable even outside its defined scope. Passing a pointer of a variable instead of the variable itself to a function, doesn’t make a copy of that variable, but instead it references the original variable.

Usage

Pointers are declared using an asterisk after the data type and before the name. The asterisk apart from declaration, is used for retrieving the value of an address pointer by the pointer. The data type of the pointer should be the same as the data type of the variable it points to.

int a = 10;
int *ptr; // Declaration
ptr = &a; // Initialization

Note: The & sign provides address of any entity. Whereas the * sign provides the value at a memory location, which is stored inside the entity,

Another method to declare a pointer is as follows:

int a = 10;
int *ptr = &a; // Declaration & Initialization

Pointers and Heap Memory

Did you know?

In C, the variables defined are stored in the stack memory by default. This although fast and automatic, is limited in size and can cause scope related issues due to abstract persistence. To counter this, dynamic memory allocation is used, which enables the use of heap memory to the programmer.

Heap Memory Allocation

Memory in heap can be allocated using the malloc() or calloc function. It takes the size of memory to allocates in bytes.

/* Initialize a string of 10 characters */
char *str = (char *) malloc(sizeof(char) * 10);

Heap Memory Deallocation

After the use of a memory space, it can be deleted using the free() function. It is essential to deallocated unused memory to avoid memory leaks.

char *str = (char *) malloc(sizeof(char) * 10);
free(str); // Frees memory pointed by str

Special Types of Pointers

Apart from regular pointers, there are some special pointers in C that are either features or security risks due to their memory unsafeness.

1. NULL Pointer

A NULL pointer is a pointer which doesn’t point to any memory location. It is ideal for a pointer to point to NULL instead of any random memory location which is not used.

int *ptr = NULL;

2. void Pointer

A void pointer is a special type of pointer which is of the data type void. That means, it can point to a variable of any data type without restrictions. Then, it can be typecasted into other data types like int*, float*, uint32_t*, char*.

int var = 32;
void *ptr = &var;
printf("%d\n", *(int *)ptr);

3. Wild Pointer

A wild pointer is an uninitialized pointer. Their contents are garbage values which could potentially point to a memory location. Hence they are unsafe and every pointer should be initialized either to NULL or a valid memory location.

int *ptr;

4. Dangling Pointer

Dangling pointers are one of the most dangerous security risks in memory management in C. They basically point to a memory location which was used earlier but was freed using free().

It is highly likely that the same memory location will be used for further storage of data. This can expose a lot of data via that pointer leading to potential unauthorized access of it.

int *ptr = (int *) malloc(sizeof(int) * 4); // Array of size 4 >> int[4]
free(ptr); // ptr is now a dangling pointer
 
ptr = NULL; // Always point a dangling pointer to NULL to avoid security risks.

Other Important Topics

Pointer Arithmetic Function Pointer