Skip to content

C Function Return Values

Updated 7 min read Aimerscrew

So far your functions have printed their results. But often you don't want a function to print anything; you want it to give you an answer that you can store, compare or calculate with. That's what C function return values are for. In this lesson, you'll learn how the return statement works, how to choose a return type, how to leave a function early, and what to do when you need more than one result.

🌍 Real-life example

A sales tax calculator at a store checkout doesn't shout the answer across the shop. You type in a price, and it hands back one number: the price with tax. The checkout then uses that number to build the receipt total. A function with a return value works the same way: inputs go in, one result comes back to whoever asked.

What is a return value in C?

A return value is the result a function sends back to its caller. Two parts of the function work together to make it happen:

  • The return type, written before the function name, says what type of value comes back (int, double, char, and so on).
  • The return statement, return expression;, ends the function and sends the value of the expression back.
#include <stdio.h>

int larger(int a, int b) {
    if (a > b) {
        return a;
    }
    return b;
}

int main(void) {
    int best = larger(8, 3);
    printf("Best score: %d\n", best);
    printf("Higher bid: %d\n", larger(250, 310));
    return 0;
}
Best score: 8
Higher bid: 310

Think of the call larger(8, 3) as a question. When the function returns, the whole call is replaced by its answer, so the line effectively becomes int best = 8;.

Diagram: in int best = larger(8, 3);, the arguments 8 and 3 go into the function larger as a and b; since 8 is greater than 3, return a sends 8 back, and the statement becomes int best = 8;
Arguments go in, one value comes back, and the call is replaced by that value.

Choosing the return type

The return type should match the kind of answer the function gives. A tax calculator works with money, so it returns a double:

#include <stdio.h>

double price_with_tax(double price, double tax_rate) {
    return price + price * tax_rate;
}

int main(void) {
    double headphones = price_with_tax(40.00, 0.08);
    double book = price_with_tax(19.99, 0.20);

    printf("Headphones: $%.2f\n", headphones);
    printf("Book:       $%.2f\n", book);
    printf("Together:   $%.2f\n", headphones + book);
    return 0;
}
Headphones: $43.20
Book:       $23.99
Together:   $67.19

The book costs 19.99 + 3.998 = 23.988, which %.2f rounds to 23.99 for display. The stored value is still 23.988, which is why the total rounds to 67.19.

The function answers...Good return typeExample
A whole number (count, score, index)intint count_vowels(...)
A measurement or pricedoubledouble average(...)
A single character or gradecharchar letter_grade(...)
Yes or no (1 or 0)int or boolint is_even(...)
Nothing; it just does a jobvoidvoid print_menu(void)

Using returned values in expressions

Because a call becomes a value, you can use it anywhere a value of that type is allowed: in arithmetic, as an argument to another call, or inside a condition.

#include <stdio.h>

int larger(int a, int b) {
    if (a > b) {
        return a;
    }
    return b;
}

int main(void) {
    int total = larger(3, 7) + larger(10, 4);
    printf("Sum of winners: %d\n", total);

    int best_of_three = larger(larger(4, 9), 6);
    printf("Best of three: %d\n", best_of_three);

    int age_a = 15;
    int age_b = 19;
    if (larger(age_a, age_b) >= 18) {
        printf("At least one adult\n");
    } else {
        printf("No adults\n");
    }
    return 0;
}
Sum of winners: 17
Best of three: 9
At least one adult

In larger(larger(4, 9), 6), the inner call runs first and returns 9, so the outer call becomes larger(9, 6), which returns 9.

Returning early from a function

A return statement ends the function immediately, even in the middle of the body. Nothing after it runs. You can use this to return as soon as you know the answer, instead of building a long if/else chain:

#include <stdio.h>

char letter_grade(int score) {
    if (score >= 90) {
        return 'A';
    }
    if (score >= 80) {
        return 'B';
    }
    if (score >= 70) {
        return 'C';
    }
    return 'F';
}

int main(void) {
    printf("95 -> %c\n", letter_grade(95));
    printf("83 -> %c\n", letter_grade(83));
    printf("70 -> %c\n", letter_grade(70));
    printf("61 -> %c\n", letter_grade(61));
    return 0;
}
95 -> A
83 -> B
70 -> C
61 -> F

For a score of 95, the first return 'A'; ends the function, so the other checks never run. That's why there's no need for else here.

Can a void function use return?

Yes. A void function returns no value, but it can still use a plain return; (with no value) to stop early. A common use is rejecting bad input:

#include <stdio.h>

void print_discount(int age) {
    if (age < 0) {
        printf("Invalid age: %d\n", age);
        return;
    }
    if (age >= 65) {
        printf("Age %d: senior discount 20%%\n", age);
        return;
    }
    printf("Age %d: no discount\n", age);
}

int main(void) {
    print_discount(70);
    print_discount(30);
    print_discount(-5);
    return 0;
}
Age 70: senior discount 20%
Age 30: no discount
Invalid age: -5

Remember that %% inside printf prints a single percent sign. When a void function reaches its closing brace, it returns automatically, so a final return; is never needed.

Can a C function return more than one value?

No. A return statement sends back exactly one value. If you write return a, b;, C uses the comma operator and returns only b. This is a classic surprise for people coming from Python functions, which can return several values at once.

When you need several results, you have three options:

  • Write separate functions, such as smallest() and largest().
  • Pass the addresses of variables for the function to fill in, using pointers (see pass by reference).
  • Group the results into a single structure and return that (see C structs).

💡 Tip

Prefer functions that return a result over functions that print it. A returned value can be printed, saved, compared or passed on; a printed value can only be read by a human. Keep the printing in main or in a dedicated output function.

Common mistakes with return values

1. Forgetting to return a value

int larger(int a, int b) {
    if (a > b) {
        return a;
    }
    /* missing: return b; */
}

When a is not larger, the function reaches its end without returning anything. GCC with -Wall warns that control reaches end of non-void function, and if the caller uses the result, it gets a garbage value. Make sure every path through the function ends in a return.

2. Losing decimals because of integer division

#include <stdio.h>

double average_wrong(int a, int b) {
    return (a + b) / 2;
}

double average_right(int a, int b) {
    return (a + b) / 2.0;
}

int main(void) {
    printf("Wrong: %.1f\n", average_wrong(7, 8));
    printf("Right: %.1f\n", average_right(7, 8));
    return 0;
}
Wrong: 7.0
Right: 7.5

A double return type doesn't help if the calculation is done with integers: 15 / 2 is already 7 before it's converted. Dividing by 2.0 fixes it (see type conversion).

3. Using the result of a void function

Writing int x = print_menu(); when print_menu returns void is an error: GCC says void value not ignored as it ought to be. There is no value to store.

4. Calling a function and ignoring its result

larger(5, 9);              /* the 9 is thrown away */
int winner = larger(5, 9); /* keep it */

This compiles without a warning, but the answer is lost. If you need the result, store it or use it directly.

Practice exercise

🏋️ Try it yourself

An online shop gives free shipping on orders of $50 or more; otherwise shipping costs $4.99. Write a function double shipping_cost(double order_total) that returns the right shipping cost, using an early return. In main, print the cart, shipping and total for carts of $35.50 and $72.00.

Show solution
#include <stdio.h>

double shipping_cost(double order_total) {
    if (order_total >= 50.0) {
        return 0.0;
    }
    return 4.99;
}

int main(void) {
    double cart = 35.50;
    printf("Cart $%.2f, shipping $%.2f, total $%.2f\n",
           cart, shipping_cost(cart), cart + shipping_cost(cart));

    cart = 72.00;
    printf("Cart $%.2f, shipping $%.2f, total $%.2f\n",
           cart, shipping_cost(cart), cart + shipping_cost(cart));
    return 0;
}
Cart $35.50, shipping $4.99, total $40.49
Cart $72.00, shipping $0.00, total $72.00

What's next?

You can now write complete functions with inputs and outputs. Next, learn how to keep main at the top of your file and organize larger programs with C function prototypes.

Key takeaways

  • The return type before a function name says what type of value the function sends back.
  • return expression; ends the function immediately and sends the value back to the caller.
  • A function call is replaced by its return value, so you can store it, print it or use it in expressions.
  • Use early returns to exit as soon as you know the answer; code after a return does not run.
  • A void function returns no value but can use a plain return; to stop early.
  • A C function returns only one value; use separate functions, pointers or structs for more.
  • Every path in a non-void function must end in a return, or the caller may get a garbage value.

Frequently asked questions

What does return do in C?

The return statement ends the current function immediately and, in a non-void function, sends a value back to the caller. The function call is then replaced by that value.

What is a return type in C?

It is the type written before a function name, such as int or double, that tells the compiler what kind of value the function returns. void means it returns nothing.

Can a C function return two values?

Not directly. A function returns exactly one value. To get several results, return a struct, or pass pointers to variables that the function fills in.

Can a void function have a return statement?

Yes, a plain return; with no value is allowed in a void function to exit early. Writing return with a value in a void function is not allowed, and modern GCC rejects it.

What happens if a non-void function has no return?

GCC warns that control reaches the end of a non-void function. If the caller uses the result, the value is undefined, usually garbage. Every path should end with a return.

Do I have to use the value a function returns?

No. You can call a function and ignore its result, and C will simply discard it. Only do this when you really do not need the answer.