A function groups reusable logic under a name, with a defined return type and parameter list.
int add(int a, int b) { // return type, name, parameters
return a + b;
}
void printGreeting(const char *name) { // void = returns nothing
printf("Hello, %s!\n", name);
}
int main(void) {
int sum = add(3, 4); // 7
printGreeting("Rahim"); // prints a greeting, returns nothing
return 0;
}
C is strictly pass-by-value: when you call add(3, 4), the function receives copies of the arguments, so any changes made to a parameter inside the function have no effect on the caller's original variables. This is why, to let a function modify a caller's variable, you must pass a pointer to it instead (covered in the Pointers chapter) — passing the value alone is never enough.
const char *name marks the pointer's target as read-only within the function — a promise to callers that printGreeting won't modify the string it's given, which the compiler will actually enforce.