Every Argument Is a Copy

One rule governs every function call in C, and half the surprises of this chapter dissolve once it is exact: arguments are passed by value. The parameter is a fresh variable, initialized with a copy of the argument; the function computes with the copy, and the caller's variable never hears about any of it. This lesson makes the rule concrete, shows the famous function it breaks, and names the two-part escape route the coming chapters build.

Watching the Copy

Inside, n becomes 100; outside, amount remains 50. The assignment was real, but it targeted the copy. Drawing the memory picture makes it obvious: main has a patch named amount holding 50; the call creates a separate patch named n, initialized to 50; the function writes 100 into its own patch, which is discarded when the function returns. Two patches, one moment of copying, no further connection.

The rule cuts both ways, and the productive direction matters as much as the surprising one: because the parameter is the function's private copy, a function can scribble on its parameters freely, decrementing counters, peeling digits, without documenting any effect on the caller. Parameters are initialized local variables, nothing more.

The Function It Breaks

The canonical casualty, on every exam since the beginning:

The output is x = 1, y = 2: nothing swapped. Inside swap, the copies exchange values flawlessly, and both copies then evaporate. No rearrangement of this function fixes it; with pass-by-value alone, no function can modify its caller's variables. When the exam presents this program and asks for the output, the unswapped values are the answer, and "the parameters are copies" is the one-line justification.

The Escape Route

The workaround you already own: return. A function that computes a new value hands it back, and the caller stores it:

The assignment happens in main, on main's variable, with the function's result. This return-and-assign shape covers every single-result function, and it is the course's default: compute in the function, store in the caller.

But return carries one value, and swap needs to change two. The real fix is to hand the function not the values but the addresses of the caller's variables, the &x you have written in every scanf since chapter 1. scanf could always modify your variables precisely because you passed addresses; making that mechanism yours is the pointers chapter, where swap returns and finally works. For now, the honest summary: pass-by-value is the rule, return is the front door, and addresses are the back door with its own chapter.

One More Consequence: Expressions as Arguments

Because only the value crosses the boundary, any expression can be an argument: cube(x + 1), doubled(doubled(5)), cube(scanf's guarded result). The expression is evaluated, the result copied in. This is also why the argument-evaluation order caution from chapter 3 applies to calls: f(i++, i) modifies and reads i with no sequencing between the arguments, undefined behaviour wearing a function call's clothes. Arguments stay side-effect-free in course code.

Key Takeaways

  • Parameters are fresh variables initialized with copies of the argument values; functions never see caller variables.
  • A function may freely modify its parameters; the caller is unaffected, in both the surprising and the useful direction.
  • The value-passing swap can never work, and its unswapped output plus the one-line reason is a standing exam answer.
  • The standard escape is return-and-assign in the caller; multiple results need addresses, scanf's trick, formalized in the pointers chapter.
  • Any expression can be an argument, but side effects in argument lists risk the unsequenced-modification UB from chapter 3.