pass-by-value
Imagine you photocopy a document and hand someone the copy. They can scribble all over their copy, but your original stays untouched. That is exactly how C passes arguments to functions: it copies the value you give and hands the function the copy. Whatever the function does to its parameter, your original variable back in the caller is unaffected.
When you call f(x), C evaluates x, makes a fresh copy of that value, and binds it to f's parameter. The parameter is a separate local variable that just happens to start with the same value. So if f assigns a new value to its parameter, only the copy changes; the caller's x keeps its original value. This is C's one and only argument-passing rule — there is no built-in pass-by-reference in C. To let a function change a caller's variable, you pass the address of that variable (a pointer): the pointer value is still copied by value, but it points back at the original, so dereferencing it reaches the real object.
Why this matters: pass-by-value is why a naive swap function that just reassigns its two int parameters does nothing to the caller's variables — a classic beginner surprise. Knowing the rule tells you exactly when you need a pointer parameter (to modify the original, or to avoid copying a large struct). And the subtle but important point: passing a pointer still passes that pointer BY VALUE; you copy the address, not the pointee.
void try_change(int n) { n = 99; } /* changes only the copy */ int x = 5; try_change(x); /* x is still 5 afterward */ /* to actually change x, pass its address: */ void set(int *p) { *p = 99; } set(&x); /* now x is 99 */
try_change edits a copy, so x is unchanged; set receives x's address and writes through it, so x really changes.
C is always pass-by-value — there is no pass-by-reference. Passing a pointer still copies the pointer (the address) by value; the function can reach the original only because the copied address still points at it.