We'll wrap up the basics of this course with one of the most fundamental concepts in C: functions (with a bonus chapter on modular programming right after this one, before we dive into the more advanced stuff).
Every C program is built on the principle we're about to explore in this chapter. We're going to learn how to structure our programs into small, manageable chunks... kind of like building with Legos.
All large C programs are really just a collection of small chunks of code — and those chunks of code are what we call... functions :D
Introduction to Functions
Way back in the first few chapters, we saw that every C program starts with a function called main.
I even made a little diagram to help you remember some terminology. Hang on, let me dig that up...
*starts rummaging through dusty archives*
Ah, here it is:
#include <stdio.h> #include <stdlib.h>int main() { printf("Hello world!\n"); return 0; }
Yep, that was from the very beginning.
At the top, we've got the preprocessor directives (a scary name we'll come back to later). They're easy to spot: they start with a #
and are usually placed right at the top of the source files.
Then, right below, we've got what I already called a "function." In our example, that's the main function (not super full, I'll admit). I told you a C program always starts with the main function. Don't worry, that's still absolutely true :D
But so far, we've stayed inside the main function. We've never left it. Look back at your source codes and you'll see — everything's been tucked inside those curly braces of main.
Not bad, exactly — but it's not really how C programmers do things in the real world.
Hardly any real C program is written entirely inside main. Our programs have been short so far, so it hasn't been a big deal, but imagine a huge project with thousands of lines of code! If everything lived inside main, it would be a total mess.
So now we're going to learn how to get organized. We're going to break our programs into small parts (remember the Lego metaphor from earlier?).
Each "small part" of a program is what we call a function.
A function performs an action and returns a result. It's a block of code meant to do one specific job.
We say a function has input and output. In simple terms, it looks like this:
Input → Function → Output
When we call a function, three things happen:
- Input: We send information into the function (we give it some data to work with)
- Processing: The function uses that data to do its job
- Output: When it's done, the function returns a result — this is the "output" or "return value"
To give you a concrete example, imagine a function called triple that takes a number and returns triple its value (by multiplying it by 3).
Of course, functions are usually more complex. The whole point of using functions is to simplify our source code — so we don't have to copy and paste the same chunk of code over and over again.
Dream a little: later on, we'll write a function like shootZombie that fires at undead enemies in a multiplayer FPS. Once we've written the function (which is the hard part), we'll just say, "Hey, shootZombie — take care of those corpses!" ;)
We could also write a function like moveCharacter to move a player around on the screen, and so on.
Function structure
You've already seen the basic layout of a function thanks to main.
But to fully understand it, I need to show you how we actually build a function.
Here's the basic structure of a function — memorize this one:
type functionName(parameters) { // Your instructions go here }
Looks familiar, right? Kind of like main.
Let's break down what's happening here:
- type (this is the output): This is the return type of the function. Just like variables, functions have types too. The type depends on what kind of value the function returns. If it returns a decimal, you'll probably use double; if it returns an integer, use int or long. And yes, it's also possible to create functions that return nothing!
- So, there are two kinds of functions:
- Functions that return a value: These use regular types like char, int, double, etc.
- Functions that return nothing: These use a special type called void (which means "empty").
- functionName: This is the name of your function. You can name it whatever you like — as long as you follow the same rules as for variables (no spaces, no accents, etc.).
- parameters (this is the input): Inside the parentheses, you can send data into the function. These are the values the function will use to do its job.
- For example, for a function triple, you would send it a number as a parameter. The function grabs that number, multiplies it by 3, and returns the result.
- You can send as many parameters as you want.
- You can also send no parameters at all — that happens too, though it's less common.
- Finally, the curly braces mark the beginning and end of the function. Inside those braces, you write whatever instructions you want. For the triple function, that would be a line that multiplies the input by 3.
- So a function is essentially a mechanism that takes input values (parameters), does something with them, and gives back a result (the return value).
Nice and clean!
Creating a Function
Let's dive straight into a practical example: the famous triple function I've been mentioning all along. We'll say this function takes an integer (int) as input and returns another integer. Its job? To calculate triple the value it receives:
int triple(int number) { int result = 0;result = 3 * number; // We multiply the input number by 3 return result; // We return the variable 'result', which now holds triple the value }
There you go — our very first function. One important thing to notice: the function is declared as int, which means it must return an int value.
Inside the parentheses, you see the variables that the function accepts. In this case, our triple function receives a single int variable named number.
The line that tells the function to return a value is the one with return
. It's usually found at the end of the function, once the calculations are done.
return result;
tells the function: "stop here and send back the value stored in result." That variable must be of type int, since the function was declared to return an int — as we said earlier ;)
The result variable is declared (i.e., created) inside the triple function. This means it can only be used within that function — not elsewhere, like in main. It's a variable that's local to the triple function.
Nope — we can actually shrink it down to just one line.
int triple(int number) { return 3 * number; }
This version does exactly the same thing as the previous one — it just gets to the point faster :)
In general, your functions will involve multiple variables to carry out their tasks, so you won't often see functions as short as triple.
Multiple Parameters, No Parameters
Multiple Parameters
Our triple function has one parameter, but you can absolutely create functions that accept multiple parameters.
For example, here's an add function that takes two numbers, a and b, and returns their sum:
int add(int a, int b) { return a + b; }
You just separate the parameters with a comma — simple as that ;)
No Parameters
Some functions — though less common — take no input at all. These functions generally do the same thing every time they're called. Since they don't receive any numbers to work with, their role is usually just to perform a fixed action, like displaying text on the screen (and even then, it'll always be the same message!).
Let's imagine a helloWorld
function that simply prints a greeting to the screen:
void helloWorld() { printf("Hello World"); }
I didn't put anything between the parentheses because the function takes no parameters.
Also, I used the void type — remember that from earlier?
That's because this function doesn't have a return line. It doesn't return anything. A function that doesn't return a value is declared as void.
Calling a Function
Time to roll up our sleeves and test out some code to practice what we just learned.
We're going to use our triple function (yes, I'm still a big fan of it!) to calculate the triple of a number.
For now, make sure you write the triple function before the main function. If you place it after, it won't work — I'll explain why later (in the next chapter, actually).
#include <stdio.h> #include <stdlib.h>int triple(int number) { return 3 * number; }
int main(int argc, char *argv[]) { int enteredNumber = 0, tripledNumber = 0; printf("Enter a number... "); scanf("%d", &enteredNumber); tripledNumber = triple(enteredNumber); printf("The triple of that number is %d\n", tripledNumber); return 0; }
As you know, our program starts with the main function.
We ask the user to enter a number. That number is sent to the triple function, and we store the result in the variable tripledNumber. Pay close attention to this line — it's the most interesting one, because it's where we call the function:
tripledNumber = triple(enteredNumber);
Inside the parentheses, we pass a variable to the triple function — it's the number it will work on. That function returns a value, which we capture in tripledNumber. So in plain English, this line says: "Ask the triple function to calculate the triple of enteredNumber, and store the result in the tripledNumber variable."
The Same Explanation, but with a Diagram
Still not quite sure how it all works? Don't worry! I've got you covered with one of my favorite teaching tools: diagrams :)
The heavily commented code below shows you the exact order the program is read. Start with line "1," then move to "2," then "3"... (you get the idea :D)
#include <stdio.h> #include <stdlib.h>int triple(int number) // 6) We jump to the triple function and receive a parameter (number) { return 3 * number; // 7) We do some math and exit the function. ‘Return' ends the function and sends back a result }
int main(int argc, char *argv[]) // 1) The program starts at the main function (this line) { int enteredNumber = 0, tripledNumber = 0; // 2) It reads this line and sets up the variables printf("Enter a number... "); // 3) Next, it reads this instruction and runs printf scanf("%d", &enteredNumber); // 4) Same here: it reads and executes scanf tripledNumber = triple(enteredNumber); // 5) Here we go — a function call! So it jumps to the triple function above printf("The triple of that number is %d\n", tripledNumber); // 8) Then we return to main and run this line return 0; // 9) A return! The main function ends, so the program is over. }
If you understood the order in which the computer reads each line, then you've already grasped the most important part :)
Now it's crucial to understand that a function receives input (called parameters), and returns output (a result).
Let's Test the Program
Here's a quick example of what the program does (nothing too crazy — it's a basic little function after all 😉):
The triple of that number is 30
And hey — you don't have to store a function's result in a variable! You can pass it straight into another function, just like you would with a regular variable. For example, you can feed the result of triple(enteredNumber)
directly into printf.
Check this out — same code, but we've changed the last printf and ditched the tripledNumber
variable, since we don't need it anymore:
#include <stdio.h> #include <stdlib.h>int triple(int number) { return 3 * number; }
int main(int argc, char *argv[]) { int enteredNumber = 0; printf("Enter a number... "); scanf("%d", &enteredNumber);
// The result of the function goes directly into printf — no need to store it printf("The triple of that number is %d\n", triple(enteredNumber)); return 0; }
As you can see, triple(enteredNumber)
is passed directly to printf.
It's simple! It sees the line starts with printf, so it prepares to call the printf function. We give printf two parameters: the text to display, and a number.
The computer realizes that before it can pass that number to printf, it needs to call the triple function first. So it jumps over to triple, runs the calculation, gets the result, and sends it right back into printf.
It's like nesting functions inside one another ;)
And the Coolest Part? A Function Can Call Another Function!
Yep, that's right — our triple function could call another function, which itself could call another... and so on! That's the beauty of C programming: everything links together like LEGO bricks :)
In the end, the hardest part will be writing your functions. Once they're written, you can just call them wherever you need, without worrying about the internal calculations. It's a huge time saver — and believe me, we'll need that as we go further! 😄
A Bunch of Examples
Let me now show you several examples of how functions are used, so you can start to see their value. I'll try to mix it up each time, giving you different use cases so you can get a feel for all the types of functions that can exist. Theory is great and all, but if we only stick to that, we're likely to forget most of it—or worse, not understand how to actually use it. That would be a shame.
You're not going to learn anything new here, but this is a great chance to go over some hands-on examples. If you've understood everything I've explained so far, awesome! None of these upcoming examples should catch you off guard.
Looking at a Function That Takes One Parameter
Let's start with a function that doesn't return anything. Picture one of those lines you had to write over and over again as punishment when you were a kid:
void punishment(int numberOfLines) { int i; for (i = 0 ; i < numberOfLines ; i++) { printf("I must not copy off my neighbor\n"); } }int main(int argc, char *argv[]) { punishment(10); return 0; }
Output:
I must not copy off my neighbor I must not copy off my neighbor [...] I must not copy off my neighbor
Here we've got a function that doesn't return any value. All it does is perform an action — in this case, print messages to the screen.
A function that doesn't return anything is written as void, which is why we started it off with that keyword.
Other than that, nothing too wild going on here 😉
Now, it would've been way more useful to have a punishment function that works for any kind of line you want to repeat. We could send it two parameters: the text to repeat, and how many times it should repeat.
But the problem is... we don't know how to handle text in C yet! (In case you hadn't noticed, we've only been working with variables that hold numbers so far.)
Speaking of which—good news! We'll be learning how to use variables that store text soon. It's a little trickier than it looks, and I didn't want to throw it at you right at the beginning of the course 😉
Looking at a Function That Takes Two Parameters
The area of a rectangle is easy to calculate: width * length.
Our function rectangleArea
will take two parameters — width and length — and return the area:
double rectangleArea(double width, double length) { return width * length; }int main(int argc, char *argv[]) { printf("Rectangle with width 5 and length 10. Area = %f\n", rectangleArea(5, 10)); printf("Rectangle with width 2.5 and length 3.5. Area = %f\n", rectangleArea(2.5, 3.5)); printf("Rectangle with width 4.2 and length 9.7. Area = %f\n", rectangleArea(4.2, 9.7)); return 0; }
Output:
Rectangle with width 5 and length 10. Area = 50.000000 Rectangle with width 2.5 and length 3.5. Area = 8.750000 Rectangle with width 4.2 and length 9.7. Area = 40.740000
Of course! In that case, the function wouldn't return anything — it would just calculate the area and immediately print it out.
void rectangleArea(double width, double length) { double area = 0; area = width * length; printf("Rectangle with width %f and length %f. Area = %f\n", width, length, area); }int main(int argc, char *argv[]) { rectangleArea(5, 10); rectangleArea(2.5, 3.5); rectangleArea(4.2, 9.7); return 0; }
As you can see, the printf is now inside the rectangleArea
function and still displays the same info as before. Just a different way of doing it.
The downside here is that since the function doesn't return anything—and we're not storing the result anywhere — we've got no way to access the area value back in main.
Looking at a Function That Takes No Parameters
Now here's a more interesting and practical bit of code. We're going to create a function menu() that doesn't take any input. This function just displays a menu and asks the user to make a choice. It then returns that choice.
int menu() { int choice = 0; while (choice < 1 || choice > 4) { printf("Welcome to Isengard Catering:\nMenu:\n"); printf("1: Grilled cucumber skewers with roasted hobbits and BBQ sauce\n"); printf("2: Grilled lembas with blueberry grog glaze\n"); printf("3: Bloody Snaga cutlet with peppered strawberry jelly\n"); printf("4: Saruman's big surprise (I'm drooling already...)\n"); printf("Your choice? "); scanf("%d", &choice); } return choice; }int main(int argc, char *argv[]) { switch (menu()) { case 1: printf("You chose the skewers\n"); break; case 2: printf("You chose the lembas\n"); break; case 3: printf("You chose the cutlet\n"); break; case 4: printf("You chose the Chef's surprise. You're quite hardcore!\n"); break; } return 0; }
I also took the liberty of making the menu a bit more robust: the menu function keeps showing the menu until the user enters a number between 1 and 4. That way, there's no chance it returns an invalid choice!
In main, you'll notice we did a switch(menu())
. Once the menu()
function is done, it returns the user's choice directly into the switch. Simple, clean, and fast!
Your turn! This code could still be improved — like showing an error message when the user enters an invalid number instead of just silently showing the menu again.
Enjoyed this C / C++ course?
If you liked this lesson, you can find the book "Learn C Programing for Beginners" from the same authors, available on SiteRaw, in bookstores and in online libraries in either digital or paperback format. You will find a complete C / C++ workshop with many exclusive bonus chapters.