Docs
Function Basics
Functions in C
📖 Introduction
A function is a self-contained block of code that performs a specific task. Functions allow you to break complex programs into smaller, manageable pieces. This promotes code reusability, readability, and easier debugging.
🎯 Why Use Functions?
Without Functions: With Functions:
┌─────────────────────────┐ ┌─────────────────────────┐
│ main() { │ │ main() { │
│ // 100 lines for │ │ readInput(); │
│ // reading input │ │ processData(); │
│ │ │ displayResults(); │
│ // 200 lines for │ │ } │
│ // processing │ │ │
│ │ │ void readInput() {...} │
│ // 100 lines for │ │ void processData() {...}│
│ // output │ │ void displayResults()...│
│ } │ └─────────────────────────┘
└─────────────────────────┘
Hard to maintain Organized & Reusable
Benefits:
| Benefit | Description |
|---|---|
| Modularity | Break code into logical pieces |
| Reusability | Write once, use many times |
| Readability | Easier to understand |
| Debugging | Isolate and fix bugs easily |
| Collaboration | Different programmers work on different functions |
📐 Function Syntax
Structure:
return_type function_name(parameter_list) {
// Function body
// Statements
return value; // Optional, based on return_type
}
Components:
┌─── Return Type (what the function gives back)
│
│ ┌─── Function Name (identifier)
│ │
│ │ ┌─── Parameters (inputs)
│ │ │
▼ ▼ ▼
int add (int a, int b)
{
return a + b; ◄─── Return Statement
}
▲
│
└─── Function Body (what it does)
🔧 Function Types
1. No Return, No Parameters:
void greet(void) {
printf("Hello, World!\n");
}
// Call:
greet();
2. No Return, With Parameters:
void printSum(int a, int b) {
printf("Sum: %d\n", a + b);
}
// Call:
printSum(5, 3); // Output: Sum: 8
3. With Return, No Parameters:
int getRandomNumber(void) {
return 42;
}
// Call:
int num = getRandomNumber();
4. With Return, With Parameters:
int add(int a, int b) {
return a + b;
}
// Call:
int result = add(10, 20); // result = 30
📊 Function Declaration vs Definition
Declaration (Prototype):
Tells the compiler about the function's signature.
// Declaration (prototype) - usually at top of file or in header
int add(int a, int b); // With parameter names (optional)
int multiply(int, int); // Without parameter names (valid)
Definition:
The actual implementation of the function.
// Definition - the full function
int add(int a, int b) {
return a + b;
}
Complete Example:
#include <stdio.h>
// Declaration (prototype)
int square(int n);
void printLine(void);
int main() {
printLine();
printf("Square of 5: %d\n", square(5));
printLine();
return 0;
}
// Definitions
int square(int n) {
return n * n;
}
void printLine(void) {
printf("-------------------\n");
}
🔄 Function Call Flow
main() square(5)
│ │
│ Call square(5) │
├────────────────────────────► │
│ │ n = 5
│ │ Calculate 5 * 5
│ │ return 25
│ Receive 25 │
│◄──────────────────────────── │
│ │
▼ Continue execution ▼
📥 Parameters and Arguments
Terminology:
- •Parameters: Variables in function definition (formal parameters)
- •Arguments: Values passed during function call (actual parameters)
// Parameters
// ↓ ↓
int add(int a, int b) {
return a + b;
}
int main() {
int x = 5, y = 10;
int sum = add(x, y); // x and y are Arguments
// ↑ ↑
// Arguments
}
Pass by Value:
C passes arguments by value - a copy is made.
void increment(int n) {
n = n + 1; // Changes local copy only!
printf("Inside: %d\n", n);
}
int main() {
int x = 5;
increment(x);
printf("Outside: %d\n", x); // Still 5!
return 0;
}
// Output:
// Inside: 6
// Outside: 5
📤 Return Values
Single Return:
int max(int a, int b) {
if (a > b) {
return a;
}
return b;
}
Multiple Return Points:
int grade(int score) {
if (score >= 90) return 'A';
if (score >= 80) return 'B';
if (score >= 70) return 'C';
if (score >= 60) return 'D';
return 'F';
}
Return with Expression:
int factorial(int n) {
if (n <= 1) return 1;
return n * factorial(n - 1);
}
void Return:
void printError(int code) {
if (code == 0) {
return; // Early exit, no value
}
printf("Error code: %d\n", code);
}
🔢 Data Types for Return
| Return Type | Description | Example |
|---|---|---|
void | No return value | void printHello() |
int | Integer | int getAge() |
float | Floating point | float getAverage() |
double | Double precision | double calculatePi() |
char | Single character | char getGrade() |
int* | Pointer | int* createArray() |
📚 Standard Library Functions
C provides many built-in functions:
stdio.h:
printf("Hello"); // Print formatted output
scanf("%d", &n); // Read input
puts("String"); // Print string with newline
getchar(); // Read single character
string.h:
strlen(str); // String length
strcpy(dest, src); // Copy string
strcmp(s1, s2); // Compare strings
strcat(dest, src); // Concatenate strings
math.h:
sqrt(x); // Square root
pow(x, y); // x to the power y
abs(x); // Absolute value
sin(x), cos(x); // Trigonometric functions
stdlib.h:
malloc(size); // Allocate memory
free(ptr); // Free memory
rand(); // Random number
atoi(str); // String to integer
🔄 Function Scope
Local Variables:
void function1() {
int x = 10; // Local to function1
printf("%d\n", x);
}
void function2() {
// x is NOT accessible here!
int y = 20; // Local to function2
}
Global Variables:
int globalVar = 100; // Accessible everywhere
void function1() {
printf("%d\n", globalVar); // Works!
}
void function2() {
globalVar = 200; // Modified!
}
Variable Scope Diagram:
┌─────────────────────────────────────────────┐
│ Global Scope │
│ int globalVar; │
│ │
│ ┌───────────────────────────────────────┐ │
│ │ function1() │ │
│ │ int localA; // Only here │ │
│ │ // globalVar accessible │ │
│ └───────────────────────────────────────┘ │
│ │
│ ┌───────────────────────────────────────┐ │
│ │ function2() │ │
│ │ int localB; // Only here │ │
│ │ // localA NOT accessible! │ │
│ └───────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────┘
🎨 Best Practices
1. Naming Conventions:
// Good - descriptive names
int calculateArea(int length, int width);
void printStudentInfo(char* name, int age);
// Bad - vague names
int calc(int l, int w);
void print(char* n, int a);
2. Single Responsibility:
// Good - one task per function
int calculateSum(int arr[], int size);
void printArray(int arr[], int size);
// Bad - doing too much
void calculateAndPrintSum(int arr[], int size);
3. Function Length:
- •Keep functions short (< 50 lines ideally)
- •If too long, break into smaller functions
4. Documentation:
/**
* Calculates the factorial of a number.
*
* @param n The number to calculate factorial for
* @return The factorial of n, or -1 if n is negative
*/
int factorial(int n) {
if (n < 0) return -1;
if (n <= 1) return 1;
return n * factorial(n - 1);
}
⚠️ Common Mistakes
1. Forgetting Return:
// Wrong - should return something
int add(int a, int b) {
int sum = a + b;
// Forgot return!
}
// Correct
int add(int a, int b) {
return a + b;
}
2. Wrong Return Type:
// Wrong - returning float but declared int
int divide(int a, int b) {
return (float)a / b; // Truncated!
}
// Correct
float divide(int a, int b) {
return (float)a / b;
}
3. Missing Prototype:
int main() {
greet(); // Error: function not declared!
return 0;
}
void greet() {
printf("Hello!\n");
}
🔑 Key Takeaways
- •Functions divide code into reusable blocks
- •Declare (prototype) before use, define anywhere
- •C uses pass by value - copies are passed
- •Use
returnto send back a value - •
voidmeans no return value - •Keep functions focused on one task
- •Use descriptive function names
⏭️ Next Topic
Continue to Function Parameters to learn about different parameter passing techniques.