Recommended resources
The freely available resources this lesson will direct you to.
Welcome back! In our last lesson, we focused on the fundamental structure of a C function, learning how to define one with parameters for input and a return statement for output. We saw how to capture that output by storing it in a variable.
Today, we'll build directly on that knowledge. The goal of this lesson is to master the different ways you can call a function and use its return value. You'll learn that a function call is more than just an instruction; it's an expression that can be used flexibly within your code, making your programs more concise and powerful.
1. The Function Call as an Expression
In the previous lesson, we used a two-step process to get and use a value from a function:
- Call the function and assign its return value to a variable.
- Use that variable in a subsequent statement (like a
printfcall).
For example:
// Step 1: Call function, store result in 'area_result'
double area_result = calculate_area(10.0, 5.0);
// Step 2: Use the variable 'area_result'
printf("The calculated area is: %f\n", area_result);
This works perfectly, but there's a more direct way. The key insight is that a function call that returns a value is itself an expression. The expression calculate_area(10.0, 5.0) evaluates to the value that the function returns (in this case, 50.0).
This means you can use a function call in almost any place you could use a variable or a literal value (like 50.0).
Let's explore a resource that clearly contrasts these two approaches.
Functions & how to use them in C programming - Detailed Explanation
This blog post by Ehoneah Obed offers a very clear, side-by-side comparison of storing a return value versus using it directly.
Please read the section titled "3. How to call a function". Focus on the two code examples under "Examples:". Notice how the first assigns the sum() result to the result variable, while the second places the sum(89, 92) call directly inside the printf function.
2. Using Return Values in Practice
Understanding that a function call is an expression opens up several powerful and common programming patterns. Let's look at a few.
A. Direct Use in Output Functions
As you just read, the most straightforward application is using a function's return value directly as an argument to another function, like printf.
Let's revisit our fahrenheitToCelsius example from the last lesson, but written more concisely:
#include <stdio.h>
float fahrenheitToCelsius(float fahrenheit) {
return (fahrenheit - 32.0) * (5.0 / 9.0);
}
int main(void) {
float temp_f = 98.6;
// Instead of using an intermediate variable, we call the function
// directly inside printf. The return value becomes the argument for %f.
printf("%.1f F is %.1f C\n", temp_f, fahrenheitToCelsius(temp_f));
return 0;
}
This is a very common and efficient way to write code, reducing the need for temporary variables.
The following video provides another excellent demonstration of capturing and using a return value.
#15 C Functions | [2025] C Programming for Beginners
This video from Programiz, which we saw in the last lesson, has a great section on functions that return values. It clearly illustrates the flow of control and data.
Watch the segment from return values. The narrator first creates a function that returns the sum of two numbers. Pay close attention to how the return sum; statement sends a value back, and how the main function captures this value in the result variable. The narrator explains that the function call is effectively replaced by its return value.
B. Use in Arithmetic and Logical Expressions
Since a function call evaluates to a value, you can seamlessly integrate it into calculations.
Imagine you have a function that calculates sales tax. You can use its return value directly when computing a final price.
#include <stdio.h>
double calculate_tax(double amount, double tax_rate) {
return amount * (tax_rate / 100.0);
}
int main(void) {
double item_price = 50.0;
double tax_rate_percent = 8.5;
double final_price;
// The call to calculate_tax() is part of an arithmetic expression.
// It evaluates to a value, which is then added to item_price.
final_price = item_price + calculate_tax(item_price, tax_rate_percent);
printf("Item price: $%.2f\n", item_price);
printf("Final price after tax: $%.2f\n", final_price);
return 0;
}
This principle is one of the main reasons functions make code so modular. You can compose complex operations by combining simpler functions. This leads us to our next point.
C. As Arguments to Other Functions
This is where the power of modularity truly shines. The return value of one function can be passed directly as an argument to another.
The CodeChef article you'll read next has a perfect example of this, where a sum_of_squares function calls a square function.
Functions in C (Examples and Practice) - CodeChef
This article from CodeChef provides excellent, practical examples of function usage.
Please read the section titled "Functions Within Functions". In the example, notice how the sum_of_squares function is defined as return square(a) + square(b);. Here, the return values from two separate calls to the square function are used immediately in an addition expression.
This pattern of "chaining" or "composing" functions is fundamental to building complex software from simple, reusable parts.
3. Your Turn: Putting It All Together
Let's practice these concepts with a small coding exercise. The following program calculates the final cost of an item after a discount is applied.
#include <stdio.h>
// Calculates the amount of a discount.
// price: The original price of the item.
// percentage: The discount percentage (e.g., 15 for 15%).
// returns: The discount amount in dollars.
double get_discount_amount(double price, double percentage) {
return price * (percentage / 100.0);
}
int main(void) {
double original_price = 120.0;
double discount_percentage = 20.0;
double final_price;
// Calculate the final price.
// The return value from get_discount_amount() is used
// immediately in the subtraction.
final_price = original_price - get_discount_amount(original_price, discount_percentage);
printf("Original price: $%.2f\n", original_price);
printf("Discount : %.0f%%\n", discount_percentage);
printf("Final price : $%.2f\n", final_price);
return 0;
}
Your Task:
- Compile and run the code above to verify its output.
- Now, let's add a sales tax calculation. Create a new function with the following signature:
double get_tax_amount(double price, double tax_rate)
This function should calculate and return the tax amount, similar to howget_discount_amountworks. - In
main, declare atax_ratevariable and set it to a value (e.g.,7.5). - Modify the calculation for
final_priceto first apply the discount, and then add the tax to the discounted price. Try to do this in a single expression! Your new calculation should look something like this:
final_price = (original_price - get_discount_amount(...)) + get_tax_amount(...);
Hint: The first argument toget_tax_amountshould be the discounted price, not the original price.
This exercise will give you hands-on practice with using function return values directly in a multi-step arithmetic expression.
Conclusion
In this lesson, we elevated our understanding of function calls from simple commands to versatile expressions. This shift in perspective is key to writing elegant and efficient C code.
Key Takeaways:
- A function call that returns a value evaluates to that value and can be treated as an expression.
- This allows you to use function calls directly within other expressions, such as:
- As arguments in a
printfstatement. - As operands in an arithmetic calculation (e.g.,
price + calculate_tax(...)). - As arguments to other functions, allowing you to chain operations together.
- As arguments in a
- Using return values directly can make your code more compact and readable by eliminating unnecessary temporary variables.
Preview of the Next Lesson:
So far, we have always defined our functions before the main function calls them. This ensures the compiler knows about the function before it's used. But what if you want to organize your code differently, perhaps defining main first or keeping functions in separate files? To do this, we need a way to tell the compiler about a function's existence ahead of its full definition. In the next lesson, we will learn how to do just that using function prototypes.