CPass by Value

Pass by Value

C has exactly one parameter-passing model: pass by value. Every single argument you give a function — an int, a double, a struct, even a pointer — is copied into the corresponding parameter. The function only ever works with its own private copy.

What "Copied" Really Means

When you call f(x), C takes the current value stored in x, copies those bytes into the memory reserved for f's parameter, and runs f. Inside f, changes to the parameter only change that copy. Once f returns, the copy is gone, and x in the caller is exactly as it was before the call (unless you explicitly reassigned it using the function's return value).

A copy, not the original

C
#include <stdio.h>

void tryToDouble(int n) {
    n = n * 2;  // modifies the local copy only
    printf("Inside tryToDouble: n = %d\n", n);
}

int main(void) {
    int value = 5;
    tryToDouble(value);
    printf("Back in main: value = %d\n", value); // unchanged!
    return 0;
}
Inside tryToDouble: n = 10
Back in main: value = 5
The Classic Broken swap

A textbook example of this trap is writing a function meant to swap two variables' values.

swap that does not actually swap anything

C
#include <stdio.h>

void swap(int a, int b) {
    int temp = a;
    a = b;
    b = temp;
    printf("Inside swap: a = %d, b = %d\n", a, b);
}

int main(void) {
    int x = 1, y = 2;
    swap(x, y);
    printf("Back in main: x = %d, y = %d\n", x, y);
    return 0;
}
Inside swap: a = 2, b = 1
Back in main: x = 1, y = 2
Why It Fails

When swap(x, y) is called, a and b are brand-new local variables that start out holding copies of x and y's values. The swap that happens inside the function is real — a and b genuinely trade values — but a and b are not x and y. They live in completely separate memory. As soon as swap returns, a and b cease to exist, and x and y in main are untouched, because nothing inside swap ever had access to x or y themselves — only to copies of their values.

  • Every argument is copied into its parameter at call time.

  • A function can never modify the caller's variable through an ordinary (non-pointer) parameter.

  • This is true no matter how complex the type is: int, double, struct Point, all copied by value.

Passing a pointer does not change this rule
It is tempting to think "just pass a pointer instead, and now it's pass by reference." That is close, but the underlying rule never changes: the *pointer itself* is still copied by value. What differs is *what* gets copied — a memory address instead of the data itself — and that copied address happens to still point at the original data, which is what lets the function reach in and modify it. The next page walks through exactly how this works and fixes `swap` for good.
Why this design?
Pass-by-value keeps function calls predictable and safe by default: a function cannot accidentally corrupt the caller's variables just by touching its parameters. When you *do* want a function to modify something in the caller, C makes you say so explicitly, by passing a pointer.
Fixing swap
Continue to the next page, Pass by Reference (Pointers), to see the corrected version of `swap` using pointers.