Pass by value, pass a pointer

Here is a rule with no exceptions: C passes every argument by value. When you call a function, the values of the arguments are copied into the parameters, which are fresh locals in the new stack frame.

So this swap does nothing useful:

void swap(int a, int b) {
    int tmp = a;
    a = b;
    b = tmp;   // swapped the copies, then the frame vanishes
}

The caller's variables never moved. The function only ever saw copies, and the copies were thrown away when it returned.

The fix is to pass addresses instead. The addresses are still copied (pass by value, always), but a copy of an address still points at the original variable:

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

swap(&x, &y);   // hand over where x and y live

Now *a and *b reach back into the caller's frame and change the real x and y.

This pattern is everywhere in C. A function can only return one value, so when it needs to hand back several, the caller passes pointers to variables and the function fills them in. These are often called out-parameters. scanf works exactly like this.

Bonus: passing a pointer to something big is cheap, because only the 4 (or 8) byte address gets copied instead of the whole thing.

Try it yourself

Edit it. Break it. Run it again.
#include <stdio.h>

void broken_swap(int a, int b) {
    int tmp = a;
    a = b;
    b = tmp;
}

void real_swap(int *a, int *b) {
    int tmp = *a;
    *a = *b;
    *b = tmp;
}

int main(void) {
    int x = 1, y = 2;
    broken_swap(x, y);
    printf("after broken_swap: x = %d, y = %d\n", x, y);
    real_swap(&x, &y);
    printf("after real_swap:   x = %d, y = %d\n", x, y);
    return 0;
}
Ctrl/Cmd + Enter runs. Esc, then Tab, leaves the editor.

Your turn

Type it yourself. That is the whole trick.

1Fix the swap

The swap function in the starter takes copies, so it cannot work. Change it to take pointers, and change the call in main to pass addresses. The program should print: x = 8, y = 3

#include <stdio.h>

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

int main(void) {
    int x = 3, y = 8;
    swap(x, y);
    printf("x = %d, y = %d\n", x, y);
    return 0;
}
Ctrl/Cmd + Enter runs. Esc, then Tab, leaves the editor.

2Two answers at once

Write void divide(int a, int b, int *quotient, int *remainder) that stores a / b and a % b through the two pointers. main is done already. Expected output: 17 / 5 = 3 remainder 2

#include <stdio.h>

void divide(int a, int b, int *quotient, int *remainder) {
    // fill in the two results through the pointers
}

int main(void) {
    int q = 0, r = 0;
    divide(17, 5, &q, &r);
    printf("17 / 5 = %d remainder %d\n", q, r);
    return 0;
}
Ctrl/Cmd + Enter runs. Esc, then Tab, leaves the editor.

Code editor. Press Control or Command plus Enter to run the code. Tab indents; to move focus out of the editor, press Escape and then Tab.