C++ Function Definitions
A function's interface names the function, its return type, and its parameters.
Try it: Defining and Calling Functions
What def and a call really do: def only creates a function object, a call binds the arguments to the parameters in a new frame and runs the body, return ends the call at once and its value replaces the call expression in the caller — while a function that only prints gives back None.
How it works
- def name(params): creates a function object and binds the name to it; the body does not run yet.
- A call evaluates its arguments, opens a new frame, binds each parameter to its argument and runs the body from the top.
- return value ends the call immediately (lines after it never run) and sends the value back; the frame and its local names are discarded.
- In the caller, the call expression is replaced by the returned value, which can be stored, used in a larger expression or passed to another call.
- A body that ends without return (e.g. one that only prints) makes the call evaluate to None — so x = f() stores None and None + 1 raises TypeError.
- Calling a name before its def has run raises NameError: the function does not exist yet.
Default run (18 steps): The program is ready. Python runs it from the top, one statement at a time. Idea: the value a call returns is what the caller stores. … The program finished. Console: 8.
Simplified: Four fixed, hand-written programs; you edit the literal arguments, switch the body between return and print, and move the def after the calls. The lab's own small evaluator runs them (your input is never executed as code); every variant was run in CPython 3.12 and the lab reproduces its sys.settrace line/call/return/exception events, its output and its error message. Functions are shown as <function name> without a memory address.
Loading the simulation…
Predicting a Program's Output
A C++ program is often split into named pieces called functions. Each piece does one job, and other pieces can call it when they need that job done. Before learning the rules, try reading a small program and predicting what it does. The program below has two function definitions and a main function that calls one of them.
- square is a value-returning function: its return type is double, so it sends a double back to its caller.
print_squarehas return type void, so it sends nothing back, but its body still writes output.- main calls
print_squarewith the argument 1.234.
What do you think happens?
Before reading on, predict exactly what the program prints when main calls print_square with 1.234.
Reveal answer
1.52276
square receives 1.234 as x and returns x times x, which is $1.234 \times 1.234 = 1.522756$. print_square sends that value to the output stream with cout. With default formatting, cout shows six significant digits, so the printed line is 1.52276.
Reading the Parts of a Definition
A function's interface names the function, its return type, and its parameters. The interface is the part of the definition that a caller needs to know in order to use the function.
Take the first line of square from the program above: double square(double x). Read it from left to right. The first word, double, is the return type, which declares what kind of value the function sends back to its caller. The next word, square, is the name that other code uses to call the function. The part in parentheses, (double x), is the parameter list. It declares the input the function expects, here one input named x of type double. The body is the block between the curly braces, and it holds the statements that do the work.
The interface and the body play different roles. A caller only needs the interface to know how to call the function and what comes back. The body is the code that carries out the work, and the caller does not need to read it to use the function.
Value-Returning Functions Versus void
The return type decides whether a function hands a result back to its caller. In square, the return type is double, and the body ends with return x * x; so the function computes a value and sends it back. In print_square, the return type is void, which means the function sends nothing back. A void function can still do work and write output in its body, which is exactly what print_square does with cout.
| Feature | Value-returning function (square) | void function (print_square) |
|---|---|---|
| Return type in the definition | double | void |
| What the caller receives | The value named in the return statement, here x times x | No value |
| Work done in the body | Computes and returns a value | Writes output with cout |
| How the caller uses it | Can place the result in an expression, such as cout << square(x) | Calls it as a statement, such as print_square(1.234); |
Two kinds of function definitions in the same program
- The return statement sends x * x back to the place where square was called.
- The caller stores that returned value in area.
Tracing main, print_square, and square
The printed line in the first program is produced through a chain of calls. main calls print_square. While building its output, print_square calls square and uses the value that square returns. To find where a result comes from, follow the chain in order: the value main passes in, the calculation and return inside square, and the use of that result inside print_square. The diagram below shows which function is active at each point, going down the calls and back up the returns.
Tracing the program line by line
Trace what happens from the moment main calls print_square(1.234) until the program prints its line and ends.
- 1Step 1: main makes the call
main calls
print_squareand passes 1.234 as the argument. The parameter x insideprint_squarereceives 1.234. - 2Step 2: print_square needs a value
The statement std::cout <<
square(x)must evaluatesquare(x)before it can print anything, soprint_squarecalls square with x. - 3Step 3: square computes and returns
square runs return x * x. With x equal to 1.234, this is $1.234 \times 1.234 = 1.522756$, and that value is returned to
print_square. - 4Step 4: print_square writes output
print_squaresends the returned value to cout. With default formatting, the line shown is 1.52276. - 5Step 5: control returns to main
print_squarehas return type void, so nothing comes back. Control returns to main, which moves on to return 0.
The program prints 1.52276. The value flowed from main into print_square, from print_square into square, and back from square into print_square for printing.
Mistakes Beginners Make Reading Definitions
Common mistake Treating the return type as the function's name
What it looks likeReading double square(double x) and thinking the function is called double.
Why it failsThe return type comes first and describes the kind of value sent back. The name comes after it.
Do this insteadIdentify the name as the word directly before the parameter list, here square.
Common mistake Expecting a void function to give back a number
What it looks likeWriting double r = print_square(2.0); and expecting r to hold the squared value.
Why it failsA void function sends nothing back to its caller, so there is no value to store.
Do this insteadCall a void function as a statement, such as print_square(2.0);, and let its body do the output.
Common mistake Assuming the output comes from main alone
What it looks likeLooking only at main and guessing the printed line without reading print_square or square.
Why it failsThe printed value is built by a chain of calls, so the calculation happens inside square.
Do this insteadFollow the chain: check the argument passed by main, the calculation and return in square, then the use of that result in print_square.
Common mistake Confusing the parameter with the argument
What it looks likeThinking that x in (double x) is the value 1.234.
Why it failsThe parameter x is a placeholder declared in the definition. The value 1.234 is the argument supplied by the caller at the call site.
Do this insteadRead the parameter list as a declaration of what input is expected, and read the call print_square(1.234) as the place where the actual value is supplied.
Practice Tracing a Changed Function
Keep the same main and print_square as above, but change square so that its body is return x + x; instead of return x * x;. Without running the program, predict the line that is printed when main calls print_square(1.234). Then name the return type of square and say whether print_square sends a value back to main.
Hints
- Start by following the call from main to
print_square, then fromprint_squareto square. - Only the calculation inside square changed. Work out what x plus x equals when x is 1.234.
- Remember that
print_squarehas return type void, so it never hands a value to main.
Key Takeaways
- A function definition's interface names the function, its return type, and its parameters; the body holds the statements that do the work.
- In the line double
square(double x), double is the return type, square is the name, and (double x) is the parameter list. - A value-returning function such as square sends a value back to its caller through a return statement, while a void function such as
print_squaresends nothing back but can still write output. - To trace a result, follow the calls from main through each function that calculates or uses the value, and then follow the returns back up the chain.
- When a result looks wrong, check the value passed in, the calculation and return inside the called function, and how the caller uses that returned result.