Skip to content

Chapter 11 of 21

Pointers

Understand addresses, dereferencing, arithmetic, arrays, and function pointers.

38 minutes 10 quick checksBy Subha Prasad
Lesson 11 of 21Course navigation

Lesson content

Read, practise, then check your understanding

A pointer stores the address of an object or function. Pointers enable output parameters, dynamic allocation, data structures, callbacks, and efficient traversal. They are powerful only when their type, validity, bounds, alignment, and pointed-to lifetime are all correct.

Address and dereference

int count = 7;
int *pointer = &count;

printf("%d\n", *pointer); // read count
*pointer = 9;              // write count

&count obtains the address and *pointer accesses the pointed-to object. Declare the pointed-to type accurately. A null pointer represents no object; compare with NULL before dereferencing when null is allowed.

Pointer parameters

C passes pointers by value, but a copied pointer can still reach the caller’s object.

void swap(int *left, int *right) {
    int temporary = *left;
    *left = *right;
    *right = temporary;
}

Document non-null requirements. Use const int * when the function only reads through the pointer.

Arrays and arithmetic

In most expressions an array converts to a pointer to its first element. array[i] is defined in terms of *(array + i). Adding one advances by the size of the pointed-to type, not one byte.

for (const int *p = values; p != values + count; ++p) {
    printf("%d\n", *p);
}

Pointer arithmetic is valid only within one array object or one position past it. The one-past pointer may be compared but not dereferenced. Subtracting two pointers into the same array produces ptrdiff_t.

Pointer levels and void pointers

int ** points to an int * and is useful when a function must replace the caller’s pointer. void * can hold an object pointer without type information; convert it back to the correct type before dereferencing. In C, malloc’s void * converts implicitly to an object pointer—do not add a cast that can hide a missing declaration.

Function pointers

int compare_ints(const void *a, const void *b) {
    int left = *(const int *)a;
    int right = *(const int *)b;
    return (left > right) - (left < right);
}

qsort(values, count, sizeof values[0], compare_ints);

The callback must match the required signature exactly. A typedef can make complex function-pointer types readable.

Invalid pointers

A pointer becomes dangling when its object’s lifetime ends or allocation is freed. Never return the address of an automatic local variable. Initialize pointers, preserve ownership rules, and set a pointer to NULL after freeing when that prevents accidental reuse—but remember other aliases may still dangle.

Knowledge check

Answer every question correctly to complete this chapter.

Which operator obtains an object’s address?
If p is an int pointer, what does p + 1 point to?
What does *p do when p points to a valid int?
What does a null pointer represent?
What is a dangling pointer?
Which pointer may read but not modify its int through that access path?
Where may a pointer legally advance in ordinary array traversal?
May the one-past-the-end pointer be dereferenced?
What is void * used for?
What must match when passing a callback function pointer?

0 of 10 checks passed

Your progress is saved on this device.