Unit 3 - Notes

CSE109

Unit 3: User defined functions and Storage classes

1. Introduction to Functions

A function is a self-contained block of statements that perform a coherent task of some kind. Every C program consists of one or more functions, one of which must be main().

Advantages of using functions:

  • Modularity: Breaks down a large program into smaller, manageable sub-problems.
  • Reusability: Code can be written once and executed multiple times.
  • Debugging: Easier to locate and isolate errors.
  • Maintenance: Logic changes need to be made in only one place.

2. Components of a Function

To use a function in C, three distinct steps are required:

2.1 Function Prototype (Declaration)

A prototype tells the compiler about the function's name, return type, and the number/type of arguments it accepts. It ensures type checking.

Syntax:

C
return_type function_name(type arg1, type arg2, ...);

Example:

C
int add(int a, int b); // Declaration

2.2 Function Definition

This is the actual code block that implements the logic of the function. It consists of the function header and the function body.

Syntax:

C
return_type function_name(type variable1, type variable2, ...) {
    // Body of the function
    // Statements
    return value; // Optional, depends on return_type
}

2.3 Function Call

This is the statement that invokes the function to perform its task.

Syntax:

C
function_name(value1, value2, ...);


3. Different Types of Functions

Functions are classified based on arguments and return values.

Type 1: No Arguments and No Return Value

The function takes no input and returns nothing (void). It is usually used for printing or display logic.

C
void printMessage() {
    printf("Hello World");
}
// Call: printMessage();

Type 2: No Arguments but Returns a Value

The function takes no input but performs a calculation and returns the result.

C
float getPi() {
    return 3.14159;
}
// Call: float p = getPi();

Type 3: Arguments but No Return Value

The function accepts data to work on but prints the result or modifies a global state rather than returning a value.

C
void displaySum(int a, int b) {
    printf("Sum is: %d", a + b);
}
// Call: displaySum(5, 10);

Type 4: Arguments and Returns a Value

The most common type. It takes input, processes it, and returns the output.

C
int multiply(int a, int b) {
    return a * b;
}
// Call: int result = multiply(5, 5);


4. Function Calling Types (Parameter Passing)

There are two ways to pass data to a function in C.

4.1 Call by Value

  • The value of the actual parameter is copied into the formal parameter.
  • Changes made to the parameters inside the function do not affect the argument in the calling function.
  • Memory is allocated separately for formal arguments.

Example:

C
void swap(int x, int y) {
    int temp = x;
    x = y;
    y = temp;
    // x and y are swapped here, but not in main
}

4.2 Call by Reference (Address)

  • The address (memory location) of the actual parameter is passed to the function.
  • Pointers are used to hold the addresses.
  • Changes made to the parameters inside the function directly affect the argument in the calling function.

Example:

C
void swap(int *x, int *y) {
    int temp = *x;
    *x = *y;
    *y = temp;
    // The original variables in main are swapped
}
// Call: swap(&a, &b);


5. Math Library Functions

C provides a standard library <math.h> for common mathematical operations. Most of these functions accept and return data of type double.

Function Description Example Result
ceil(x) Rounds up to the nearest integer ceil(3.2) 4.0
floor(x) Rounds down to the nearest integer floor(3.9) 3.0
sqrt(x) Calculates square root sqrt(16.0) 4.0
pow(x, y) Calculates x raised to power y pow(2.0, 3.0) 8.0
abs(x) Absolute value (integer) <stdlib.h> abs(-5) 5
fabs(x) Absolute value (float) fabs(-5.5) 5.5
sin(x) Sine of x (x in radians) sin(0.0) 0.0
log(x) Natural logarithm (base e) log(10.0) 2.30

6. Recursion

Recursion is a process where a function calls itself directly or indirectly. A recursive function solves a problem by solving a smaller instance of the same problem.

Essential Components:

  1. Base Case: The condition that stops the recursion to prevent an infinite loop (Stack Overflow).
  2. Recursive Case: The part where the function calls itself.

Example: Factorial of a number

C
int factorial(int n) {
    if (n == 0) // Base Case
        return 1;
    else        // Recursive Case
        return n * factorial(n - 1);
}

Pros vs. Cons:

  • Pros: Code is cleaner and more mathematical for problems like Tree traversal or Tower of Hanoi.
  • Cons: Uses more memory (stack space) and is generally slower than iteration (loops) due to function call overhead.

7. Scope Rules

7.1 Local Scope

  • Variables declared inside a function or block.
  • Visibility: Only within the function/block where they are declared.
  • Lifetime: Created when the block is entered, destroyed when exited.

7.2 Global Scope

  • Variables declared outside all functions (usually at the top of the program).
  • Visibility: Accessible by all functions in the program.
  • Lifetime: Persists for the entire duration of the program execution.

8. Storage Classes in C

Storage classes determine four aspects of a variable:

  1. Storage Location: Where the variable is stored (RAM or Register).
  2. Default Initial Value: Value if not initialized by the user.
  3. Scope: Where the variable can be accessed.
  4. Lifetime: How long the variable stays in memory.

There are four storage classes in C:

8.1 Auto (Automatic)

  • Keyword: auto
  • Storage: RAM (Stack).
  • Default Value: Garbage value.
  • Scope: Local to the block.
  • Lifetime: Within the block.
  • Note: All local variables are auto by default.

C
void func() {
    auto int a = 10; // Same as: int a = 10;
}

8.2 Extern (External)

  • Keyword: extern
  • Storage: RAM (Data Segment).
  • Default Value: Zero.
  • Scope: Global (can be accessed in other files if linked).
  • Lifetime: Throughout the program execution.
  • Usage: Used to tell the compiler that the variable is defined elsewhere (in another file or later in the same file).

C
extern int x; // Declaration (no memory allocated yet)
int x = 10;   // Definition (memory allocated)

8.3 Register

  • Keyword: register
  • Storage: CPU Registers.
  • Default Value: Garbage value.
  • Scope: Local to the block.
  • Lifetime: Within the block.
  • Usage: Used for frequently accessed variables (like loop counters) to speed up execution.
  • Constraint: You cannot use the & (address of) operator on a register variable because it does not have a memory address.

C
register int i;
for(i = 0; i < 1000; i++) { ... }

8.4 Static

  • Keyword: static
  • Storage: RAM (Data Segment).
  • Default Value: Zero.
  • Scope: Local to the block (if inside a function) or Local to the file (if global).
  • Lifetime: Throughout the program execution.
  • Unique Feature: A static variable preserves its value between function calls. It is initialized only once.

Example of Static:

C
void counter() {
    static int count = 0; // Initialized only once
    count++;
    printf("%d ", count);
}

int main() {
    counter(); // Output: 1
    counter(); // Output: 2 (remembers previous value)
    counter(); // Output: 3
}

Summary Table of Storage Classes

Class Keyword Storage Default Value Scope Lifetime
Automatic auto Stack Garbage Local Local
External extern Data Segment Zero Global Global
Static static Data Segment Zero Local Global
Register register CPU Register Garbage Local Local