A function packages a computation behind a name and a prototype. C passes every argument by value — the function receives copies; to modify the caller’s variable you pass its address.
Declaration, definition, call
#include <stdio.h>
double average(const int *values, int count); /* prototype */
int main(void) {
int marks[] = {70, 85, 90};
printf("%.2f\n", average(marks, 3));
return 0;
}
double average(const int *values, int count) { /* definition */
if (count == 0) return 0.0;
long sum = 0;
for (int i = 0; i < count; i++) sum += values[i];
return (double)sum / count;
}81.67| Part | Example | Notes |
|---|---|---|
| Return type | double | void if nothing is returned |
| Name | average | External linkage by default; static to hide it |
| Parameters | (const int *values, int count) | (void) means no parameters; () means unspecified (pre-C23) |
| Body | { … } | return expr; ends the call |
Call by value
#include <stdio.h>
void broken_swap(int a, int b) { /* swaps the copies only */
int t = a; a = b; b = t;
}
void swap(int *a, int *b) { /* receives addresses ("call by reference" emulation) */
int t = *a; *a = *b; *b = t;
}
int main(void) {
int x = 1, y = 2;
broken_swap(x, y);
printf("after broken_swap: %d %d\n", x, y);
swap(&x, &y);
printf("after swap: %d %d\n", x, y);
return 0;
}after broken_swap: 1 2
after swap: 2 1Arrays and structs as parameters
An array argument decays to a pointer to its first element:
void f(int a[])is exactlyvoid f(int *a). The size is lost — pass it separately.A
structis copied in full. For big structs passconst struct T *to avoid the copy.Mark pointer parameters you don’t modify as
const— it documents intent and lets the compiler check it.
Returning several values
#include <stdio.h>
/* return a status, deliver results through out-parameters */
int divide(int a, int b, int *quot, int *rem) {
if (b == 0) return -1;
*quot = a / b;
*rem = a % b;
return 0;
}
int main(void) {
int q, r;
if (divide(17, 5, &q, &r) == 0)
printf("17 = 5 * %d + %d\n", q, r);
if (divide(1, 0, &q, &r) != 0)
printf("division by zero rejected\n");
return 0;
}17 = 5 * 3 + 2
division by zero rejectedinline and the order of evaluation
static inline int sq(int x) { return x * x; }— a hint to expand the body at the call site; typical in headers as a type-safe macro replacement.The order in which arguments are evaluated is unspecified: in
f(g(), h())either may run first. Never depend on it.A function with a non-
voidreturn type that falls off the end withoutreturn— and whose value is used — is undefined behaviour (-Wreturn-type).
int sign(int x) {
if (x > 0) return 1;
if (x < 0) return -1;
} /* missing return when x == 0 */Does C support call by reference?
What is a function prototype and why is it needed?
What is the difference between f() and f(void) in a declaration?