Unit 5: Arrays, User-Defined Functions, and Pointers

Table of Contents

1. Arrays

An array is a fixed-size, sequential collection of elements of the same data type. Elements are stored in contiguous memory locations and are accessed using an index.

One-dimensional Arrays

Common Mistake: Accessing an array "out of bounds." If an array is int arr[5], the valid indices are 0, 1, 2, 3, 4. Accessing arr[5] is an error that C will not stop, and it will corrupt your program's memory.

2. User-defined Functions

A function is a self-contained block of code that performs a specific task. You have used built-in functions like printf; C also lets you create your own.

Need for Functions

Elements of User-defined Functions

A function has three parts:

  1. Function Declaration (Prototype): Tells the compiler the function's name, return type, and parameters. It's placed at the top of the file.
    int add(int a, int b); // This is a function prototype
  2. Function Definition: This is the actual code for the function.
    int add(int a, int b) { // Function header
        // Function body
        int sum = a + b;
        return sum;
    }
  3. Function Call: This is how you execute the function from main() or another function.
    int main() {
        int result = add(5, 10); // This is a function call
        return 0;
    }

Return Values and their Types

A function can send a single value back to the code that called it using the return keyword.

Category of Functions

Functions can be categorized based on whether they take arguments (input) or return a value (output).

  1. No Arguments and No Return Values: Good for printing menus or fixed messages.
    void printHello() {
        printf("Hello!");
    }
  2. Arguments but No Return Values: Takes data in but doesn't send a result back.
    void printNumber(int n) {
        printf("The number is %d", n);
    }
  3. Arguments with Return Values: The most common type. Takes data, processes it, and returns the result.
    int add(int a, int b) {
        return a + b;
    }
  4. No Arguments but Returns a Value: Good for getting input from the user.
    int getAge() {
        int age;
        printf("Enter age: ");
        scanf("%d", &age);
        return age;
    }

Passing Arrays to Functions

When you pass an array to a function, C does not create a copy. Instead, it passes a pointer (the address) to the first element.

This means the function can modify the original array in main().

// 'arr' is actually a pointer (int*)
void doubleArray(int arr[], int size) {
    for (int i = 0; i < size; i++) {
        arr[i] = arr[i] * 2; // Modifies the original array
    }
}

int main() {
    int myNums[] = {1, 2, 3};
    doubleArray(myNums, 3);
    // myNums is now {2, 4, 6}
    return 0;
}

Recursion

Recursion is a process where a function calls itself, either directly or indirectly. It's a powerful alternative to loops for solving problems that can be broken into smaller, similar sub-problems.

A recursive function must have:

  1. Base Case: A condition that stops the recursion.
  2. Recursive Step: The part that calls the function again, but with a smaller problem.
// Example: Factorial
long factorial(int n) {
    if (n == 0) {
        return 1; // Base Case
    } else {
        return n * factorial(n - 1); // Recursive Step
    }
}
Common Mistake: Forgetting the base case. This will cause the function to call itself forever, leading to a "Stack Overflow" error as the program runs out of memory.

3. Pointers

Introduction to pointers in C (Basic Concepts)

A pointer is a special variable that stores the memory address of another variable.

There are two key pointer operators:

int x = 10;   // A normal variable
int *p;     // 'p' is a pointer to an integer

p = &x;     // Assign the ADDRESS of 'x' to 'p'

// Now 'p' "points to" 'x'

printf("Value of x: %d\n", x);   // Prints 10
printf("Address of x: %p\n", &x); // Prints the address (e.g., 0x7ffc1234)
printf("Value of p: %p\n", p);   // Prints the same address (0x7ffc1234)
printf("Value at p: %d\n", *p);  // Prints 10 (goes to address, gets value)

*p = 20; // Go to the address 'p' holds and change the value
printf("New value of x: %d\n", x); // Prints 20
Pointers are the most powerful and complex part of C. They are essential for modifying variables inside functions (pass-by-reference), dynamic memory allocation, and building data structures like linked lists.