Functions in C: How to Write and Use Them
Functions in C are named blocks of code that perform a specific task and can be reused as many times as you need. You write a function once, give it inputs (parameters), and it returns a result. Functions make programs shorter, easier to read, and far easier to debug.
What Is a Function in C?
A function groups a set of statements under one name. Instead of repeating the same logic everywhere, you call the function by its name. Every C program already uses one function: main(), where execution begins.
Think of a function like a tea stall calculation. You give it the number of cups, it gives back the total taka. You do not rewrite the math each time, you just ask for the result.
There are two kinds of functions: library functions (like printf() and scanf() from the standard library) and user-defined functions that you write yourself. This article focuses on writing your own.
Function Declaration, Definition, and Call
Three steps are involved when you use a function in C.
Declaration (prototype): tells the compiler the function's name, return type, and parameter types before it is used. Definition: the actual body with the code. Call: where you run the function.
#include <stdio.h>
// Declaration (prototype)
int add(int a, int b);
int main(void) {
int sum = add(5, 3); // Call
printf("Sum = %d\n", sum);
return 0;
}
// Definition
int add(int a, int b) {
return a + b;
}
The prototype ends with a semicolon; the definition does not. If you define a function above main(), the separate prototype is optional, but prototypes keep larger programs organized.
The Anatomy of a Function
A function header has four parts: return type, name, parameter list, and the body in curly braces.
return_type function_name(parameter_list) {
// body: statements
return value; // optional, depends on return type
}
Use a clear name that describes the action, such as calculateTotal or isPrime. Good names make code readable months later.
Parameters and Return Values
Parameters are the inputs a function accepts. Arguments are the actual values you pass when calling it. The return value is the result the function sends back, using the return keyword.
A function that returns nothing uses the void return type. A function that takes no input uses void (or empty parentheses) in its parameter list.
#include <stdio.h>
// Returns nothing, takes one parameter
void greet(int times) {
for (int i = 0; i < times; i++) {
printf("Assalamu Alaikum!\n");
}
}
// Takes no parameter, returns an int
int getYear(void) {
return 2026;
}
int main(void) {
greet(3);
printf("Year: %d\n", getYear());
return 0;
}
A function can have many parameters separated by commas, but each needs its own type. You cannot write int a, b; you must write int a, int b.
Pass by Value vs Pass by Reference (Pointers)
By default, C passes arguments by value. The function receives a copy, so changes inside the function do not affect the original variable. This is safe but means you cannot modify the caller's data directly.
#include <stdio.h>
void tryToChange(int x) {
x = 100; // changes only the copy
}
int main(void) {
int n = 5;
tryToChange(n);
printf("%d\n", n); // still prints 5
return 0;
}
To let a function modify the original, pass the variable's address using a pointer. This is called pass by reference. The function receives the memory location and edits the value there.
#include <stdio.h>
void changeValue(int *x) {
*x = 100; // changes the original
}
int main(void) {
int n = 5;
changeValue(&n); // pass the address
printf("%d\n", n); // prints 100
return 0;
}
The & operator gets a variable's address; the * operator dereferences a pointer to reach the value. A classic use is swapping two numbers.
#include <stdio.h>
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
int main(void) {
int x = 10, y = 20;
swap(&x, &y);
printf("x = %d, y = %d\n", x, y); // x = 20, y = 10
return 0;
}
Without pointers, the swap function would swap only copies and the originals would stay unchanged.
Recursion: A Function That Calls Itself
A recursive function calls itself to solve a smaller version of the same problem. Every recursive function needs a base case that stops the recursion, otherwise it runs forever and crashes (stack overflow).
Calculating a factorial is the standard example. The factorial of 5 is 5 × 4 × 3 × 2 × 1.
#include <stdio.h>
int factorial(int n) {
if (n <= 1) { // base case
return 1;
}
return n * factorial(n - 1); // recursive case
}
int main(void) {
printf("5! = %d\n", factorial(5)); // 120
return 0;
}
Recursion can make code elegant for problems like factorials, Fibonacci numbers, and tree traversal. For simple counting tasks, a loop is usually faster and uses less memory, so choose the tool that fits the problem.
Why Functions Matter
Functions deliver three big benefits. Reusability: write once, call anywhere. Readability: a well-named function explains what the code does without comments. Easier debugging: when something breaks, you check one small function instead of hundreds of lines.
As your programs grow, splitting logic into small functions keeps everything manageable. This habit also prepares you for larger languages like C++, Java, and Python, where the same ideas apply.
Common Mistakes to Avoid
Beginners often hit the same errors. Watch for these.
- Forgetting the semicolon after a prototype, or adding one after the definition.
- Mismatched return type, such as declaring
intbut returning nothing. - Passing a value when the function expects an address (missing
&). - Writing recursion without a base case, causing a crash.
- Expecting a pass-by-value function to change the original variable.
Compile with warnings enabled, for example gcc -Wall program.c, and the compiler will catch many of these for you.
Frequently Asked Questions
What is the difference between a parameter and an argument?
A parameter is the variable named in the function definition, like int a. An argument is the real value you pass when calling, like add(5, 3) where 5 and 3 are arguments. People use the terms loosely, but that is the precise distinction.
Can a C function return more than one value?
Not directly with return, which sends back a single value. To return multiple results, pass pointers as parameters and write the answers through them, or return a struct that bundles several values together. Pointers are the most common approach for beginners.
When should I use recursion instead of a loop?
Use recursion when a problem naturally breaks into smaller identical subproblems, such as tree traversal or factorial math. For simple repetition like counting or summing an array, a loop is clearer and more efficient. Both can solve the same problems, so pick readability.
What does the void keyword mean in a function?
As a return type, void means the function returns no value. In the parameter list, void means the function takes no arguments. For example, void printMenu(void) neither accepts input nor returns anything; it just performs an action.
Keep Practicing
Start small: write functions for addition, finding the maximum of two numbers, and checking if a number is even. Then try pointer-based swaps and a recursive factorial. Type every example yourself instead of copying, because muscle memory builds real understanding.
Strong C fundamentals open doors in software, embedded systems, and backend roles across Dhaka, Chattogram, and beyond. If you are ready to turn these skills into a job, explore current openings at Avian™ Career.
Categories
- Tutorial
- Announcement
- News