Skip to content

Pointers#

C provides a special data type known as a pointer for storing memory addresses. There are two types of pointers depending on how the memory at the stored address should be treated:
- A pointer to a variable stores the memory address of a variables.
- A pointer to a function or a function pointer stores the memory address of a function (since the code of functions is stored in memory as well).

Declaring a pointer to variable is done in the following way:

data-type *pointer;

Example: Pointer to Variable

The following is a declaration of a pointer to int:

int *ptr;

Important

Each pointer must have an asterisk (*) before its name:

int *ptr, notAPointer;

Here, ptr is a pointer to int, but notAPointer is just an int.

Declaring a function pointer is done in the following way:

return-type (*pointer)(param-type-1, param-type-2, ...);

You can optionally give names to the parameters as well:

return-type (*pointer)(param-type-1 param1, param-type-2 param2, ...);

Example: Pointer to Function

The following is a declaration of a pointer ptr to a function returns an int and takes two parameters - a double and a pointer to float:

int (*ptr)(double, float*);
int (*ptr)(double doubleParam, float *floatPointerParam);

The following is a declaration of a pointer ptr to a function which returns nothing and takes one parameter which is another function pointer to a functions which returns an int and takes no parameters:

void (*ptr)(int (*)());
void (*ptr)(int (*func)());

Address-Of Operator#

We can assign a value to a pointer as we would do with any other variable:

int *ptrToInt = 0x66f1;
double (*ptrToFunc)(int) = 0x900010;

However, this is not very useful because we are rarely aware of the underlying memory layout. Instead, we can use the address-of operator (&) to obtain the address of another object in memory:

int var = 4;
int *pointerToVar = &var; // pointerToVar holds the memory address of var
double func(int p) 
{
    return (double) (p / 2);
}

// ...

double (*ptrToFunc)(int) = &func; // ptrToFunc holds the memory address of func

For function pointers, the address-of operator can also be omitted:

double (*ptrToFunc)(int) = func;

Dereferencing#

Pointers are useful because they allow us to access variables indirectly. If we have a pointer data-type *pointer, we can access the memory at the stored address and treat it as data-type by using the dereference operator (*).

int var = 1;
int *pointerToVar = &var; // pointerToVar is now equal to the address of var
*pointerToVar = 2; // var is now equal to 2
*pointerToVar += 4; // var is now equal to 6
int anotherVar = *ip; // anotherVar is now equal to var, which is six