Functions
Chapter 1 briefly used main without explaining what makes a function "known" to the compiler. This chapter covers that directly — and sets up the exact problem pointers exist to solve next.
Function Syntax
Declarations vs. Definitions
A declaration (or prototype) tells the compiler a function exists and its exact signature — return type, name, parameter types — without providing a body. A definition provides the actual body. C compiles top to bottom in a single pass: calling a function before the compiler has seen either its declaration or its definition is an error. Rust, by contrast, allows calling any function defined anywhere in the same module, in any order — no forward declaration needed.
Header Files
A .h file conventionally holds declarations, shared across multiple .c files via #include — the mechanism that lets one source file call a function defined in a completely different one. Course 2's Multi-File Projects & Makefiles chapter covers this in full; for now, know that a header is essentially a shared table of "these functions exist, here are their signatures."
Pass-by-Value by Default
Function arguments are copied into the function — modifying a parameter inside the function has no effect on the caller's original variable. This is genuinely worth a three-way comparison: Go is also pass-by-value by default, exactly like C — a rare point of agreement between the two. Rust is the outlier, requiring an explicit choice: pass by value (moves or copies), or pass a reference (&T/&mut T) deliberately.
Simulating Pass-by-Reference With Pointers
To let a function genuinely modify the caller's variable, C requires passing a pointer explicitly — the caller's address, not its value. This is exactly what the very next chapter covers in depth; for now, just recognize that "I need the function to change my variable" is the specific problem pointers solve.
| Concept | C | Go | Rust |
|---|---|---|---|
| Default argument passing | by value (copy) | by value (copy) | by value — moves or copies |
| Passing a reference | explicit pointer (&var) | explicit pointer (&var) | explicit reference (&var / &mut var) |
| Forward declaration needed? | yes — top-to-bottom compilation | no | no |
int and accept the code — a real, dangerous default mostly removed in modern C, but worth recognizing if reading older, pre-standard codebases.
Coding Challenges
Write a function multiply(int a, int b) that returns the product of its two arguments, declared with a prototype above main and defined below it. Call it from main and print the result.
📄 View solutionWrite a function that attempts to double an int parameter by reassigning it inside the function body. Call it from main with a variable set to 10, then print the variable afterward. Explain the output.
📄 View solutionExplain why Rust doesn't require forward declarations for functions defined later in the same file, while C does — what does this reveal about how each language's compiler actually processes source code?
📄 View solutionChapter 5 Quick Reference
- Declaration/prototype — signature only, no body; definition — the actual body
- C compiles top to bottom — a function must be declared or defined before it's called
- Header files (.h) — shared declarations across multiple .c files, via #include
- Arguments are passed by value by default — a real point of agreement with Go, unlike Rust's explicit reference choice
- Modifying a parameter inside a function never affects the caller's variable — pointers (next chapter) are how C works around this
- Next chapter: arrays — fixed size, no bounds checking, and the first real "manual control" moment