Skip to content
Educora
Intermediate18 min6 / 8

Pointers

Get a variable's address in memory, read and change a value through a pointer, understand pointer arithmetic and how pointers relate to arrays, and write a swap function.

Check yourself
In this lesson you will learn
  • Get an address with & and read or change the value a pointer points to with *
  • Change the caller's variables by passing pointers to a function
  • Explain pointer arithmetic and why arr[i] is the same as *(arr + i)
  • Recognize the danger of NULL and uninitialized pointers

To show a friend where you live, you don't carry your house over — you just give the address: “Baku, Nizami Street, 25”. Someone who knows the address can find the house, go inside and even change something there. Computer memory works the same way: every variable lives at a certain address. A variable that stores an address is called a pointer. Pointers are C's most powerful and most feared topic, but the idea is as simple as that address.

Addresses and pointers

Definition
Pointer

A variable whose value is the memory address of another variable. int *p; means “p stores the address of an int”.

SyntaxMeaning
int *p;declares a pointer to an int
&xthe address of the variable x
p = &x;p now points to x
*pthe value at the address in p (dereferencing)
NULLa pointer that points to nothing
C
#include <stdio.h>

int main(void) {
    int x = 10;
    int *p = &x;
    printf("x = %d\n", x);
    printf("*p = %d\n", *p);
    *p = 25;
    printf("x = %d\n", x);
    printf("Same address? %d\n", p == &x);
    return 0;
}
Expected output
x = 10
*p = 10
x = 25
Same address? 1
*p = 25; changed x without mentioning its name, because p holds its address.

You can print the address itself with the %p specifier. It usually looks like a hexadecimal number such as 0x7ffd… and may be different every time you run the program:

C
int x = 10;
int *p = &x;
printf("Address of x: %p\n", (void *) &x);
printf("Value of p:   %p\n", (void *) p);

Passing pointers to functions: swap

Remember: in C a function receives copies of its arguments, so you cannot swap two variables through ordinary parameters. The solution is to give the function the addresses of the variables. Through the addresses, the function reaches the original variables. This is exactly why scanf("%d", &age) needs the &.

C
#include <stdio.h>

void swap(int *a, int *b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}

int main(void) {
    int x = 3, y = 8;
    printf("Before: x = %d, y = %d\n", x, y);
    swap(&x, &y);
    printf("After:  x = %d, y = %d\n", x, y);
    return 0;
}
Expected output
Before: x = 3, y = 8
After:  x = 8, y = 3

Pointers also let a function “return” several results: return gives back only one value, but a function can write its results to the addresses it was given. The function below finds the lowest and highest of several temperatures measured in Baku:

C
#include <stdio.h>

void min_max(const int *arr, int n, int *min, int *max) {
    *min = arr[0];
    *max = arr[0];
    for (int i = 1; i < n; i++) {
        if (arr[i] < *min) *min = arr[i];
        if (arr[i] > *max) *max = arr[i];
    }
}

int main(void) {
    int temps[5] = {18, 25, 21, 30, 16};
    int low, high;
    min_max(temps, 5, &low, &high);
    printf("Min: %d, max: %d\n", low, high);
    return 0;
}
Expected output
Min: 16, max: 30

Pointer arithmetic and arrays

In expressions, an array's name turns into the address of its first element, so you can write int *p = arr;. Adding 1 to a pointer moves it forward by one element, not by one byte: usually 4 bytes for an int *. So *(p + 2) is the third element, and arr[i] is simply a short form of *(arr + i). When you pass an array to a function, what is really passed is a pointer to its first element — that is why the function can change the original array and why the sizeof trick does not work on a parameter.

C
#include <stdio.h>

int main(void) {
    int arr[4] = {10, 20, 30, 40};
    int *p = arr;
    printf("%d\n", *p);
    printf("%d\n", *(p + 2));
    p++;
    printf("%d\n", *p);
    printf("%d\n", arr[3] == *(arr + 3));
    int sum = 0;
    for (int *q = arr; q < arr + 4; q++) {
        sum += *q;
    }
    printf("Sum: %d\n", sum);
    return 0;
}
Expected output
10
30
20
1
Sum: 100
p++ moved the pointer to the next element. The last loop walks through the array with a pointer instead of an index.

Dangerous pointers

  • An uninitialized pointer holds a random address. Writing through it can destroy other data. Always initialize a pointer with a variable's address or with NULL.
  • **Dereferencing a NULL pointer** (*p while p is NULL) usually crashes the program at once. Check before use: if (p != NULL).
  • A dangling pointer points to a variable that no longer exists. For example, if a function returns the address of its own local variable, that variable disappears when the function ends.
C
int *make_number(void) {
    int local = 5;
    return &local;
}
A BUG example: local disappears when the function ends, and the returned address points to “nothing”. The result is unpredictable.

Key points

  • A pointer stores an address: int *p = &x; — p is the address of x.
  • & gives the address; * reads or changes the value at that address.
  • A function that receives pointers can change the caller's variables (swap, scanf).
  • p + 1 moves one element forward; arr[i] means *(arr + i).
  • Always initialize pointers, check for NULL, and never return the address of a local variable.

Check yourself

10 questions. Every correct answer earns XP.

1 / 10
After int x = 4; int *p = &x; *p = 9;, what is x?