Functions I
CEN111 Algorithms and Programming I
Modularizing Programs in C
• Most computer programs that solve real-world problems are much
larger than those presented in the first few chapters
• You develop and maintain programs using smaller pieces, each of
which is more manageable than the original program
• This technique is called divide and conquer
Modularizing Programs in C
• Use functions to modularize programs by combining the new
functions you write with prepackaged C standard library functions
• The C standard library provides a rich collection of functions
• Prepackaged functions make your job easier because they provide
many of the capabilities you need.
• The C standard includes the C language and its standard library
• Avoid Reinventing the Wheel
• Familiarize yourself with and use the rich collection of C standard library
functions
Modularizing Programs in C
Defining Functions
• The statements defining the function are written once and are hidden from
other functions
Calling and Returning from Functions
• Functions are invoked by a function call
• A common analogy for this is the hierarchical form of management
• A boss (the calling function or caller) asks a worker (the called function) to
perform a task and report back when it’s done
• The boss function does not know how the worker function performs its
designated task
• The worker may call other worker functions, and the boss will be unaware
of this
Modularizing Programs in C
Functions
• main is often a group of calls to functions that perform the bulk of the program’s
work.
• Motivations for “functionalizing” a program
• The divide-and-conquer approach makes program development more
manageable
• Software reusability – building new programs by using existing functions
• With good function naming and definition, you can create programs from
standardized functions that accomplish specific tasks, rather than custom code
• This is known as abstraction
• Each function should be limited to performing a single, well-defined task, and the
function name should express that task
• It’s usually best to break such a function into smaller functions—a process called
decomposition
Function Definitions
• Each program we’ve presented has consisted of a function called
main that called standard library functions to accomplish its tasks.
• Now we consider how to write custom functions.
• Consider a program that uses a function square to calculate and
print the squares of the integers from 1 to 10
square Function: Example
1. #include <stdio.h>
2.
3. int square(int number); // function prototype
4.
5. int main(void) {
6.
7. for (int x = 1; x <= 10; ++x) {
8. printf("%d ", square(x)); // function call
9. }
10.}
square Function: Example
11.// square function definition returns the square of
its parameter
12.int square(int number) { // number is a copy of the
function's argument
13. return number * number; // returns square of
number as an int
14.}
Output:
1 4 9 16 25 36 49 64 81 100
square Function: Calling Function
• square is invoked or called in line 8:
• printf("%d ", square(x)); // function call
• Receives a copy of the argument x’s value in the parameter number
(line 12).
• Calculates number * number and passes the result back to line 8
in main where square was invoked.
• Line 8 passes square’s result to function printf, which displays
the result on the screen
square Function: Function Definition
• square’s definition (lines 12–14) shows that it expects an int parameter
number
• int preceding the function name (line 12) indicates square returns an
integer result
• return statement in square passes the result of number * number
back to the calling function.
• Choosing meaningful function names and meaningful parameter names
makes programs more readable and helps avoid excessive comments
• A function requiring a large number of parameters may be performing too
many tasks
• return type, name and parameter list should fit on one line if possible
square Function: Local Variables
• All variables defined in function definitions are local variables
• They can be accessed only in the function in which they’re defined
• Most functions have parameters that enable communicating
between functions via arguments in function calls
• Parameters are also local variables of that function.
square Function: Function Prototype
• Line 3 is a function prototype
• int square(int number); // function prototype
• int in parentheses informs the compiler that square expects to receive an integer
value from the caller
• int to the left of the function name informs the compiler that square returns an
integer result to the caller.
• Forgetting the semicolon at the end of a function prototype is a syntax error
• The compiler compares square’s call (line 8) to its prototype to ensure that:
• the number of arguments is correct,
• the arguments are of the correct types,
• the argument types are in the correct order, and
• the return type is consistent with the context in which the function is called.
square Function: Function Prototype
• The function prototype, first line of the function definition and function calls
should all agree in the number, type and order of arguments and parameters
• The function prototype and function header must have the same return type
Format of a Function Definition
• The format of a function definition is
• return-value-type function-name(parameter-list) {
statements
}
• function-name is any valid identifier
• return-value-type is the type of result returned to the caller
• void indicates that a function does not return a value
• return-value-type, function-name and parameter-list are the function header
• parameter-list is a comma-separated list of parameters required to call the function
when it’s called
• void for no parameters.
• Each parameter must include its type
• Placing a semicolon after the parameter-list’s right parenthesis in a function definition is
an error
Function Body
• The statements within braces form the function body, which also is a
block
• Local variables can be declared in any block, and blocks can be nested
• Functions cannot be nested
• defining a function inside another function is a syntax error
Returning Control from a Function
• There are three ways to return control from a called function to the
point at which a function was invoked
• If the function does not return a result, control is returned simply
when the function-ending right brace is reached, or by executing the
statement
• return;
• If the function does return a result, the following statement returns
the expression’s value to the caller.
• return expression;
Main’s Return Type
• main’s int return value indicates whether the program executed
correctly
• The C standard indicates that main implicitly returns 0 if you omit
the return statement at the end of main
• You can explicitly return nonzero values from main to indicate that a
problem occurred during your program’s execution
maximum Function
• Consider a custom maximum function that returns the largest of
three integers.
• maximum returns its result to main via the return statement in
line 28
• The printf statement in line 14 then prints the value returned by
maximum
maximum Function
1. // Finding the maximum of three integers.
2. #include <stdio.h>
3.
4. int maximum(int x, int y, int z); // function prototype
5.
6. int main(void) {
7. int number1 = 0; // first integer entered by the user
8. int number2 = 0; // second integer entered by the user
9. int number3 = 0; // third integer entered by the user
10.
11. printf("%s", "Enter three integers: ");
12. scanf("%d%d%d", &number1, &number2, &number3);
13.
14.printf("Maximum is: %d\n", maximum(number1, number2,
number3));
15.}
maximum Function
16.// Function maximum definition
17.int maximum(int x, int y, int z) {
18. int max = x; // assume x is largest
19.
20. if (y > max) { // if y is larger than max,
21. max = y; // assign y to max
22. }
23.
24. if (z > max) { // if z is larger than max,
25. max = z; // assign z to max
26. }
27.
28. return max; // max is largest value
29.}
Function Prototypes
• Compiler uses function prototypes to validate function calls
• Include function prototypes for all functions to take advantage of C’s
type-checking capabilities
• A function prototype (omitting the semicolon) is generally the same
as the functions definition’s first line without the semicolon
• Include parameter names in function prototypes for documentation
purposes
• The compiler ignores these names
Function Prototypes
• Another important feature of function prototypes is argument
coercion
• implicitly converting arguments to the appropriate type
• In general, argument values that do not correspond precisely to the
function prototype’s parameter types are converted to the proper
type before the function is called
• Such conversions can lead to incorrect results
• For example, converting a double to an int may lose data
Function Prototypes
• If there’s no function prototype for a function, the compiler forms
one from the first occurrence of the function—either the function
definition or a call to the function. This typically leads to warnings or
errors, depending on the compiler.
• Always include function prototypes for the functions you define or
use in your program to help prevent compilation errors and warnings.
• A function prototype placed outside any function definition applies to
all calls to the function appearing after the function prototype. A
function prototype placed in a function body applies only to calls in
that function made after that prototype.
Reference
• C How to Program, Ninth Edition by Deitel & Deitel, Pearson, 2022.