What is a Function?
In programming, a function is a self-contained block of code within a larger program, designed to perform a specific task. In C, functions are the fundamental building blocks of functionality—each function encapsulates logic to achieve a defined goal. When designing a function, parameters and return values are determined by the task it solves. A C program is essentially a collaboration of multiple functions, where each handles a sub-task to complete complex operations.
Function Classification (By Implementer)
| Function Type | Implementer |
|---|---|
| Library Funcsions | Implemented by compiler vendors (e.g., GCC) following ANSI C standards (e.g., printf, scanf). |
| User-Defined Functions | Written by programmers to meet custom requirements. |
| System Calls | Low-level functions provided by the operating system. |
Notes on Library Functions:
The C standard defines interfaces (e.g., printf’s behavior), but the actual implementation (code) is provided by compiler vendors. To use a library function, include its header file (e.g., #include <stdio.h> for printf).
Function Parameters
Function Structure
A function’s basic structure: ret_type func_name(parameters) { /* Function Body */ }
ret_type: Return type (e.g.,int,voidfor no return value).func_name: Name of the function (used to call it).parameters: Input values (or placeholders) for the function.- Function Body: Implements the logic. For non-
voidfunctions, areturnstatement with the result is required.
Example: Find the Larger Number
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
// Function definition: Return the larger of two integers
int findMax(int num1, int num2) {
return (num1 > num2) ? num1 : num2;
}
int main() {
int val1, val2;
scanf("%d %d", &val1, &val2);
int result = findMax(val1, val2); // Function call
printf("Larger value: %d\n", result);
return 0;
}
Analysis of the Code:
- The
mainfunction is the program’s entry point. val1andval2are inputs. ThefindMaxfunction compares them.- Formal vs. Actual Parameters: The parameters
num1andnum2(infindMax) are formal parameters (local copies). The values passed (val1,val2) are actual parameters (arguments).
Parameter Types
1. Actual Parameters (Arguments)
- The real values passed to a function (e.g., variables, constants, expressions, or function calls).
- Must have a definite value at the time of the function call (to pass to formal parameters).
2. Formal Parameters (Parameters)
- Variables declared in the function definition (e.g.,
num1,num2infindMax). - Act as local variibles for the called function, allocated memory only during the function call, and destroyed afterward.
- Note: Actual and formal parameters can have the same name.
Example: Addition Function
int add(int a, int b) { // Formal parameters: a, b
return a + b;
}
int main() {
int x = 5, y = 3; // Actual parameters: x, y
int sum = add(x, y);
printf("Sum: %d\n", sum);
return 0;
}
Pass-by-Value vs. Pass-by-Address (Swap Example)
Pass-by-Value (No Effect on Actual Parameters)
void swapByValue(int a, int b) {
int temp = a;
a = b;
b = temp;
}
int main() {
int x = 10, y = 20;
swapByValue(x, y); // x and y remain unchanged
printf("x: %d, y: %d\n", x, y);
return 0;
}
Pass-by-Address (Modifies Actual Parameters)
void swapByAddress(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
int main() {
int x = 10, y = 20;
swapByAddress(&x, &y); // Pass addresses of x and y
printf("x: %d, y: %d\n", x, y);
return 0;
}
Array Parameter Passing (Key Point)
When passing arrays to functions, follow these rules:
- The number of formal and actual array parameters must match (or be logically consistent).
- A one-dimensional array’s formal parameter can omit the size (e.g.,
void func(int arr[])orvoid func(int *arr)). - For two-dimensional arrays, the number of columns cannot be omitted (e.g.,
void func(int arr[][3])—rows can be omitted, but columns cannot). - The formal parameter does not create a new array; it operates on the original array passed as the actual parameter.
Example: Sum of an Array
int sumArray(int arr[], int size) {
int sum = 0;
for (int i = 0; i < size; i++) {
sum += arr[i];
}
return sum;
}
int main() {
int nums[] = {1, 2, 3, 4, 5};
int size = sizeof(nums) / sizeof(nums[0]);
int total = sumArray(nums, size);
printf("Total: %d\n", total);
return 0;
}
Function Calling
Calling Categories
- Pass-by-Value: The formal parameter is a copy of the actual parameter; modifying the formal parameter does not affect the actual parameter (e.g.,
findMax,add). - Pass-by-Address: The formal parameter receives the address of the actual parameter; modifying the formal parameter affects the actual parameter (e.g.,
swapByAddress).
Chained Function Calls
A function’s return value can be used as a parameter for another function ("chaining").
Example: Nested printf
#include <stdio.h>
int main() {
// The innermost printf prints "42" (2 characters) and returns 2.
// The middle printf prints "2" (1 character) and returns 1.
// The outermost printf prints "1".
printf("%d\n", printf("%d", printf("%d", 42)));
return 0;
// Output: 4221
}
Function Declaration and Definition
Declaration
- Tells the compiler about a function (name, parameters, return type) without providing the implementation.
- Must appear before the function is called ("declare before use").
- Typically placed in header files (
.h).
Example: Leap Year Check (Single File)
// Declaration (before main)
int isLeapYear(int year);
int main() {
int y;
scanf("%d", &y);
if (isLeapYear(y)) {
printf("%d is a leap year.\n", y);
} else {
printf("%d is not a leap year.\n", y);
}
return 0;
}
// Definition (implementation)
int isLeapYear(int year) {
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
Multi-File Collaboration
For larger projects, split functions into multiple files (e.g., add.h, add.c, main.c):
add.h(Header File): Declare the function:int add(int a, int b);add.c(Source File): Define the function:#include "add.h" int add(int a, int b) { return a + b; }main.c(Main File): Call the function:#include "add.h" #include <stdio.h> int main() { printf("%d\n", add(3, 5)); return 0; }
Benefits of Multi-File Structure
- Logical Clarity: Separate functionality into modules (e.g., input, calculation, output).
- Collaboration: Multiple developers can work on different files simultaneously.
- Code Hiding: Expose only necessary interfaces (via headers), keeping implementation details private.
Function Recursion
What is Recursion?
Recursion is a programming technique where a function calls itself. The key idea is to break a large problem into smaller, similar sub-problems ("divide and conquer").
Two Essential Conditions for Recursion
- Base Case: A condition that stops the recursion (otherwise, it becomes infinite).
- Progressive Reduction: Each recursive call brings the problem closer to the base case.
Example: Print Digits of a Number
void printDigits(int n) {
if (n > 9) { // Base case not met—continue recursion
printDigits(n / 10); // Recursive call (smaller problem)
}
printf("%d ", n % 10); // Print the current digit (base case or final step)
}
int main() {
int num = 1234;
printDigits(num); // Output: 1 2 3 4
return 0;
}
In this example, printDigits calls itself with n / 10 (reducing the problem) until n <= 9 (base case), then prints each digit from the most significant to least significant.