If part 5 taught you how to guide the control flow with conditionals and loops, this chapter is where you wrap that flow into named chunks. A function lets you wrap the "input -> processing -> output" pattern with a name so that you can reuse it whenever you like. This matters because you do not want to type the same block ten times. We will separate declarations from definitions and see how to design parameters and return values.
New Terms in This Chapter
- Function Declaration: The statement that tells the compiler a function's name, parameters, and return type
- Function Definition: The code block that implements the actual behavior
- Parameter: The placeholder inside a function that receives input when the function is called
- Return Value: The value a function hands back after it finishes its computation
- Function Prototype: A declaration written above
mainso the compiler knows the function signature in advance
Key Ideas
Study Notes
- Time: about 50–60 minutes
- Prep: a few conditional and loop examples ready to modify
- Goal: understand how to declare, define, and call functions, and how to design parameters and return values
Functions are tools for naming repeated code. Even if you only use a function once, a good name explains "what it does," which makes reading much easier. Think of each function as having five parts. In int add_two_numbers(int a, int b) { return a + b; }, the return type is int, the function name is add_two_numbers, the parameters are int a, int b, the body is inside { }, and the return statement sends the result back.
- Return type: the data type of the result (
int,void,double, and so on) - Function name: verbs such as
print_lineorcalculate_totalwork well - Parameter list: the inputs the function needs
- Body: the block of code inside braces that does the work
- return statement: required whenever the return type is not
void
Follow Along with Code
Creating the Smallest Function
#include <stdio.h>
void print_separator(void) {
printf("----------\n");
}
int main(void) {
print_separator();
printf("Starting the C function lesson\n");
print_separator();
return 0;
}
print_separator uses void because it does not return anything. Calling the name inside main executes the code. Grouping repeated output into one function reduces mistakes and makes the intent obvious.
Accepting Input with Parameters
#include <stdio.h>
int add_two_numbers(int a, int b) {
return a + b;
}
int main(void) {
int result = add_two_numbers(12, 30);
printf("Result: %d\n", result);
return 0;
}
a and b only exist inside the function. When you call add_two_numbers(12, 30), the parameters are filled just for that call and disappear when the function ends. That is what makes the same function reusable with many inputs.
Returning a Result
#include <stdio.h>
double average_score(int sum, int count) {
if (count == 0) {
return 0.0;
}
return (double)sum / count;
}
int main(void) {
double avg = average_score(273, 3);
printf("Average: %.2f\n", avg);
return 0;
}
Because the return type is double, the return statement must produce a double. When parameter and return types disagree, the compiler can emit warnings or errors, so keeping the types aligned matters.
Splitting Declaration and Definition with a Prototype
#include <stdio.h>
double celsius_to_fahrenheit(double c); // function prototype
int main(void) {
double result = celsius_to_fahrenheit(24.0);
printf("24°C = %.1f°F\n", result);
return 0;
}
double celsius_to_fahrenheit(double c) {
return (c * 9.0 / 5.0) + 32.0;
}
If you prefer to define the function below main, place the prototype above so the compiler already knows the signature. Later, when you split code into multiple files, these prototypes move into header files.
Practical Example: Grouping Grade Helpers
#include <stdio.h>
int is_pass(int score) {
return score >= 60;
}
void print_report(int score) {
if (is_pass(score)) {
printf("Score %d: pass\n", score);
} else {
printf("Score %d: extra practice\n", score);
}
}
int main(void) {
print_report(85);
print_report(42);
print_report(73);
return 0;
}
is_pass returns 1 or 0 based on the score, and print_report uses that result to choose a message. Combining small functions like this keeps conditionals and loops easy to read.
Why It Matters
- Functions give names to repeated control-flow patterns, which cuts down on bugs.
- Clear parameters and return values make testing easier and help you guard against bad input.
- Separating declarations from definitions prepares you for working with multiple
.cfiles and headers. - Thinking in terms of functions narrows down where a bug might live: "which behavior is broken?"
Practice in CodeSandbox
The sandbox below uses CodeSandbox's Universal starter. For C, the key learning loop is still compile and run in the terminal, so recreate the lesson code as a source file and repeat that cycle directly.
💬 댓글
이 글에 대한 의견을 남겨주세요