C Tutorial
C Function Parameters
Pass by value copies. Pass a pointer to let the function change the caller’s variable.
Parameters are the inputs
The names in the parentheses of a definition are parameters. The values you write at the call site are arguments. C matches them in order: the first argument initializes the first parameter, the second argument the second parameter.
How that initialization works is the subject of this chapter. A plain type copies. A pointer parameter receives an address, so the function can write through it and change the caller’s object. An array argument decays to a pointer to the first element.
Pass by value copies
void bump(int n) receives its own int. Assigning to n changes the copy. The variable in main stays the same. That is safe and simple for small types.
Example
#include <stdio.h>
void bump(int n) {
n = n + 1;
printf("inside: %d\n", n);
}
int main(void) {
int coins = 10;
bump(coins);
printf("after: %d\n", coins);
return 0;
}The program prints inside: 11 and after: 10. bump never sawcoins. It saw a copy of the number 10. Use pass by value when the function should read a number (or compute from it) and leave the caller’s variable alone.
Pass a pointer to mutate the caller
C has no reference parameters. To change the caller’s variable, pass its address. void bump(int *n)receives a pointer. *n = *n + 1 writes through to the object in main.
Example
#include <stdio.h>
void bump(int *n) {
*n = *n + 1;
}
int main(void) {
int coins = 10;
bump(&coins);
printf("coins: %d\n", coins);
return 0;
}After bump(&coins), coins is 11. The argument is&coins, the address. Inside the function, n is int *. Forgetting the& at the call, or forgetting * inside the function, is the usual first bug.
Arrays decay to pointers
When you pass an array to a function, the function receives a pointer to the first element. It does not receive the length. Pass the count as a second argument. sizeof on that parameter would measure the pointer, not the array.
Example
#include <stdio.h>
void print_all(int *nums, int n) {
for (int i = 0; i < n; i++) {
printf("%d\n", nums[i]);
}
}
int main(void) {
int nums[3] = {10, 20, 30};
print_all(nums, 3);
return 0;
}print_all(nums, 3) is the same as print_all(&nums[0], 3). Insideprint_all, nums[i] is the same as *(nums + i). Stay insiden slots.
Choose copy or pointer
| Parameter | What happens | Use when |
|---|---|---|
int n | Copy | Small input you will not write back |
int *n | Address, writable | The caller’s variable must change |
int *nums, int n | Array decays; length is separate | Walk a list of ints |
Returning a value is still the cleanest way to produce a new result: compute inside the function, thenreturn it. Reach for a pointer when several fields of a struct must change together, or when a swap has to exchange two existing variables.
Compile these at /c/try. Change coins and watch the copy stay put, then the pointer version update.
Next: a function that calls itself, with a base case so the chain stops.
Worked examples
The short listings above are there so you can see the grammar. The programs here use the same statements on quantities that already have units: a speed, a pH, a count of bases. They are classroom numbers. Air resistance is ignored. g is 9.81 m/s² unless a line says otherwise.
Open them in the C editor at /c/try. Change one measurement and check whether the result still has the right unit.
Maths
Hypotenuse by value
A 5-12-13 triangle is another integer right triangle: 25 + 144 = 169. Passing a and b copies the numbers. The function cannot change the caller’s a. It only returns c.
c = √(a² + b²)
Example
#include <stdio.h>
#include <math.h>
double hypot_leg(double a, double b) {
return sqrt(a * a + b * b);
}
int main(void) {
printf("c = %.1f\n", hypot_leg(5.0, 12.0));
return 0;
}Physics
Impulse on a momentum
Impulse J equals change in momentum: J = F Δt = Δp. Adding 4 N·s to 10 kg·m/s leaves 14 kg·m/s. To change the caller’s p, pass its address. A copy would add 4 to a temporary and throw it away.
Δp = F Δt
Example
#include <stdio.h>
void apply_impulse(double *momentum, double joule_s) {
*momentum += joule_s;
}
int main(void) {
double p = 10.0;
apply_impulse(&p, 4.0);
printf("p = %.1f kg m/s\n", p);
return 0;
}