CPass by Reference (Pointers)

Pass by Reference (Pointers)

C does not have true reference parameters the way C++ does (with int &a). Instead, C simulates "pass by reference" by passing a pointer — the memory address of a variable — as the argument. The function can then follow that pointer back to the original variable and modify it directly.

Fixing swap With Pointers

Recall the broken swap from the previous page: it swapped its own local copies and had no effect on the caller. Here is the corrected version.

swap that actually works

C
#include <stdio.h>

void swap(int *a, int *b) {
    int temp = *a;  // dereference: read the value a points to
    *a = *b;        // write through a's pointer
    *b = temp;      // write through b's pointer
}

int main(void) {
    int x = 1, y = 2;
    swap(&x, &y); // pass the ADDRESSES of x and y
    printf("x = %d, y = %d\n", x, y);
    return 0;
}
x = 2, y = 1
What Changed, Exactly

The pass-by-value rule from the previous page still holds perfectly here — a and b are still copies, and they are still local to swap. The difference is what is being copied: instead of copying the integers 1 and 2, we copy the addresses of x and y. Those copied addresses still point at the exact same memory that x and y occupy, so dereferencing them with *a and *b reads and writes the real variables in main.

At the call site

In the function definition

Meaning

swap(&x, &y)

void swap(int *a, int *b)

Pass the address of a variable

&x

"Address of x" — produces a pointer to x

*a

"Value pointed to by a" — dereference to read/write the original

The Syntax, Piece by Piece
  • At the call site, prefix the variable with & (the address-of operator) to get a pointer to it: swap(&x, &y).

  • In the function definition, declare the parameter as a pointer with *: void swap(int *a, int *b).

  • Inside the function body, prefix the pointer parameter with * (the dereference operator) to read or write the value it points to: *a = *b;.

When You Need This Pattern

Pass-by-reference via pointers is the standard C technique whenever you need a function to:

  • Modify one of the caller's variables directly (like swap).

  • Return more than one value, by writing results through several output-parameter pointers.

  • Avoid copying a large struct or array just to read it, by passing a pointer to it instead (often combined with const to promise the function will not modify it).

Returning multiple values via output parameters

C
#include <stdio.h>

// Computes both quotient and remainder, "returning" two values
void divide(int dividend, int divisor, int *quotient, int *remainder) {
    *quotient = dividend / divisor;
    *remainder = dividend % divisor;
}

int main(void) {
    int q, r;
    divide(17, 5, &q, &r);
    printf("17 / 5 = %d remainder %d\n", q, r);
    return 0;
}
Not the same as C++ references
In C++, `void swap(int &a, int &b)` lets you write `a = b;` with no `*` at all — the compiler handles the indirection for you. C has no such feature; pointers and the `*`/`&` operators are always explicit. This is more verbose, but it also makes it obvious, at both the call site and inside the function, exactly where indirection is happening.
A null or invalid pointer is dangerous
If you dereference a pointer that is `NULL` or that does not point to valid memory, the behavior is undefined — typically a crash. Before writing `*a = ...`, make sure `a` genuinely points to a valid `int` that the caller intended to share with you.
Formalizing this
The next page, Function Prototypes, looks at how the compiler uses parameter types — including pointer types — to catch mistakes like this at compile time rather than at runtime.