c

examples

examples.c๐Ÿ”ง
/**
 * =============================================================================
 * POINTERS AND FUNCTIONS - EXAMPLES
 * =============================================================================
 * 
 * This file demonstrates the interaction between pointers and functions in C:
 *   - Passing pointers as function parameters
 *   - Call by value vs call by reference
 *   - Returning pointers from functions
 *   - Function pointers
 *   - Callback functions
 *   - Generic programming with void pointers
 * 
 * Compile: gcc -o examples examples.c -Wall
 * Run: ./examples
 * =============================================================================
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


/* ============================================================
 * EXAMPLE 1: Call by Value vs Call by Reference
 * ============================================================ */

void byValue(int x) {
    x = 999;  // Only modifies local copy
    printf("  Inside byValue: x = %d\n", x);
}

void byReference(int *x) {
    *x = 999;  // Modifies original through pointer
    printf("  Inside byReference: *x = %d\n", *x);
}

void example1_value_vs_reference(void) {
    printf("\n=== EXAMPLE 1: Call by Value vs Call by Reference ===\n\n");
    
    int a = 10, b = 10;
    
    printf("Initial values: a = %d, b = %d\n\n", a, b);
    
    // Call by value
    printf("Calling byValue(a):\n");
    byValue(a);
    printf("After byValue: a = %d (unchanged!)\n\n", a);
    
    // Call by reference
    printf("Calling byReference(&b):\n");
    byReference(&b);
    printf("After byReference: b = %d (changed!)\n\n", b);
    
    printf("Summary:\n");
    printf("  byValue(a)      โ†’ a stays %d (copy was modified)\n", 10);
    printf("  byReference(&b) โ†’ b becomes %d (original modified)\n", 999);
}


/* ============================================================
 * EXAMPLE 2: Swapping Variables
 * ============================================================ */

// Wrong way - doesn't work
void swapWrong(int a, int b) {
    int temp = a;
    a = b;
    b = temp;
}

// Correct way - using pointers
void swapCorrect(int *a, int *b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}

void example2_swap(void) {
    printf("\n=== EXAMPLE 2: Swapping Variables ===\n\n");
    
    int x = 10, y = 20;
    
    printf("Original: x = %d, y = %d\n\n", x, y);
    
    // Wrong way
    printf("Calling swapWrong(x, y)...\n");
    swapWrong(x, y);
    printf("After swapWrong: x = %d, y = %d (no change!)\n\n", x, y);
    
    // Correct way
    printf("Calling swapCorrect(&x, &y)...\n");
    swapCorrect(&x, &y);
    printf("After swapCorrect: x = %d, y = %d (swapped!)\n", x, y);
}


/* ============================================================
 * EXAMPLE 3: Modifying Arrays Through Pointers
 * ============================================================ */

void doubleArray(int *arr, int size) {
    for (int i = 0; i < size; i++) {
        arr[i] *= 2;  // Or: *(arr + i) *= 2;
    }
}

void example3_modify_array(void) {
    printf("\n=== EXAMPLE 3: Modifying Arrays Through Pointers ===\n\n");
    
    int arr[] = {1, 2, 3, 4, 5};
    int size = 5;
    
    printf("Original array: ");
    for (int i = 0; i < size; i++) printf("%d ", arr[i]);
    printf("\n");
    
    doubleArray(arr, size);
    
    printf("After doubleArray: ");
    for (int i = 0; i < size; i++) printf("%d ", arr[i]);
    printf("\n");
    
    printf("\nNote: Arrays are always passed by reference in C.\n");
}


/* ============================================================
 * EXAMPLE 4: Returning Pointers from Functions
 * ============================================================ */

// Safe: returning pointer to static variable
int* getStaticValue(void) {
    static int value = 42;
    return &value;
}

// Safe: returning dynamically allocated memory
int* createArray(int size, int initialValue) {
    int *arr = (int*)malloc(size * sizeof(int));
    if (arr == NULL) return NULL;
    
    for (int i = 0; i < size; i++) {
        arr[i] = initialValue;
    }
    return arr;  // Caller must free!
}

// Returns pointer to maximum element
int* findMax(int *arr, int size) {
    if (size <= 0) return NULL;
    
    int *maxPtr = arr;
    for (int i = 1; i < size; i++) {
        if (arr[i] > *maxPtr) {
            maxPtr = &arr[i];
        }
    }
    return maxPtr;
}

void example4_return_pointers(void) {
    printf("\n=== EXAMPLE 4: Returning Pointers from Functions ===\n\n");
    
    // Static variable example
    int *staticPtr = getStaticValue();
    printf("Static value: %d\n", *staticPtr);
    
    // Modify the static value
    *staticPtr = 100;
    printf("After modification: %d\n\n", *getStaticValue());
    
    // Dynamic allocation example
    int *arr = createArray(5, 7);
    if (arr != NULL) {
        printf("Dynamic array: ");
        for (int i = 0; i < 5; i++) printf("%d ", arr[i]);
        printf("\n");
        free(arr);
    }
    
    // Finding maximum example
    int numbers[] = {23, 67, 12, 89, 45};
    int *maxPtr = findMax(numbers, 5);
    printf("\nArray: {23, 67, 12, 89, 45}\n");
    printf("Maximum element: %d at address %p\n", *maxPtr, (void*)maxPtr);
}


/* ============================================================
 * EXAMPLE 5: Returning Multiple Values
 * ============================================================ */

void getMinMax(const int *arr, int size, int *min, int *max) {
    if (size <= 0) return;
    
    *min = *max = arr[0];
    
    for (int i = 1; i < size; i++) {
        if (arr[i] < *min) *min = arr[i];
        if (arr[i] > *max) *max = arr[i];
    }
}

void divideWithRemainder(int dividend, int divisor, int *quotient, int *remainder) {
    *quotient = dividend / divisor;
    *remainder = dividend % divisor;
}

void example5_multiple_return_values(void) {
    printf("\n=== EXAMPLE 5: Returning Multiple Values ===\n\n");
    
    // Min and max
    int arr[] = {45, 12, 89, 23, 56, 7, 78};
    int min, max;
    
    getMinMax(arr, 7, &min, &max);
    printf("Array: {45, 12, 89, 23, 56, 7, 78}\n");
    printf("Minimum: %d\n", min);
    printf("Maximum: %d\n\n", max);
    
    // Division with remainder
    int q, r;
    divideWithRemainder(17, 5, &q, &r);
    printf("17 รท 5 = %d remainder %d\n", q, r);
}


/* ============================================================
 * EXAMPLE 6: Function Pointers Basics
 * ============================================================ */

int add(int a, int b) { return a + b; }
int subtract(int a, int b) { return a - b; }
int multiply(int a, int b) { return a * b; }
int divide_int(int a, int b) { return b != 0 ? a / b : 0; }

void example6_function_pointers(void) {
    printf("\n=== EXAMPLE 6: Function Pointers Basics ===\n\n");
    
    // Declare function pointer
    int (*operation)(int, int);
    
    int a = 20, b = 5;
    
    // Point to add
    operation = add;
    printf("Using add:      %d + %d = %d\n", a, b, operation(a, b));
    
    // Point to subtract
    operation = subtract;
    printf("Using subtract: %d - %d = %d\n", a, b, operation(a, b));
    
    // Point to multiply
    operation = multiply;
    printf("Using multiply: %d * %d = %d\n", a, b, operation(a, b));
    
    // Point to divide
    operation = divide_int;
    printf("Using divide:   %d / %d = %d\n", a, b, operation(a, b));
    
    printf("\nFunction pointer address: %p\n", (void*)operation);
}


/* ============================================================
 * EXAMPLE 7: Array of Function Pointers
 * ============================================================ */

void example7_function_pointer_array(void) {
    printf("\n=== EXAMPLE 7: Array of Function Pointers ===\n\n");
    
    // Array of function pointers
    int (*operations[4])(int, int) = {add, subtract, multiply, divide_int};
    const char *names[] = {"Addition", "Subtraction", "Multiplication", "Division"};
    
    int x = 12, y = 4;
    
    printf("Performing all operations on %d and %d:\n\n", x, y);
    printf("โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”\n");
    printf("โ”‚ Operation        โ”‚ Result โ”‚\n");
    printf("โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค\n");
    
    for (int i = 0; i < 4; i++) {
        printf("โ”‚ %-16s โ”‚ %6d โ”‚\n", names[i], operations[i](x, y));
    }
    
    printf("โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜\n");
}


/* ============================================================
 * EXAMPLE 8: Callback Functions
 * ============================================================ */

typedef void (*ElementCallback)(int);

void forEachElement(int *arr, int size, ElementCallback callback) {
    for (int i = 0; i < size; i++) {
        callback(arr[i]);
    }
}

void printElement(int x) {
    printf("%d ", x);
}

void printSquare(int x) {
    printf("%d ", x * x);
}

void printDouble(int x) {
    printf("%d ", x * 2);
}

void example8_callbacks(void) {
    printf("\n=== EXAMPLE 8: Callback Functions ===\n\n");
    
    int arr[] = {1, 2, 3, 4, 5};
    int size = 5;
    
    printf("Array: {1, 2, 3, 4, 5}\n\n");
    
    printf("Using printElement callback:\n  Elements: ");
    forEachElement(arr, size, printElement);
    printf("\n");
    
    printf("\nUsing printSquare callback:\n  Squares: ");
    forEachElement(arr, size, printSquare);
    printf("\n");
    
    printf("\nUsing printDouble callback:\n  Doubles: ");
    forEachElement(arr, size, printDouble);
    printf("\n");
}


/* ============================================================
 * EXAMPLE 9: Sorting with Comparison Callback
 * ============================================================ */

typedef int (*CompareFunc)(const void*, const void*);

void bubbleSort(int *arr, int size, CompareFunc compare) {
    for (int i = 0; i < size - 1; i++) {
        for (int j = 0; j < size - 1 - i; j++) {
            if (compare(&arr[j], &arr[j+1]) > 0) {
                int temp = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = temp;
            }
        }
    }
}

int compareAscending(const void *a, const void *b) {
    return *(const int*)a - *(const int*)b;
}

int compareDescending(const void *a, const void *b) {
    return *(const int*)b - *(const int*)a;
}

void example9_sort_callback(void) {
    printf("\n=== EXAMPLE 9: Sorting with Comparison Callback ===\n\n");
    
    int arr1[] = {64, 34, 25, 12, 22, 11, 90};
    int arr2[] = {64, 34, 25, 12, 22, 11, 90};
    int size = 7;
    
    printf("Original array: ");
    for (int i = 0; i < size; i++) printf("%d ", arr1[i]);
    printf("\n\n");
    
    // Sort ascending
    bubbleSort(arr1, size, compareAscending);
    printf("Sorted ascending:  ");
    for (int i = 0; i < size; i++) printf("%d ", arr1[i]);
    printf("\n");
    
    // Sort descending
    bubbleSort(arr2, size, compareDescending);
    printf("Sorted descending: ");
    for (int i = 0; i < size; i++) printf("%d ", arr2[i]);
    printf("\n");
}


/* ============================================================
 * EXAMPLE 10: Using typedef with Function Pointers
 * ============================================================ */

// Define types for clarity
typedef int (*BinaryOp)(int, int);
typedef void (*Action)(void);

int power(int base, int exp) {
    int result = 1;
    for (int i = 0; i < exp; i++) {
        result *= base;
    }
    return result;
}

int modulo(int a, int b) {
    return a % b;
}

void sayHello(void) {
    printf("Hello!\n");
}

void sayGoodbye(void) {
    printf("Goodbye!\n");
}

void example10_typedef_function_pointers(void) {
    printf("\n=== EXAMPLE 10: Using typedef with Function Pointers ===\n\n");
    
    // Using BinaryOp type
    BinaryOp ops[] = {add, multiply, power, modulo};
    const char *names[] = {"add", "multiply", "power", "modulo"};
    
    printf("Using BinaryOp typedef:\n");
    for (int i = 0; i < 4; i++) {
        printf("  %s(3, 4) = %d\n", names[i], ops[i](3, 4));
    }
    
    // Using Action type
    Action actions[] = {sayHello, sayGoodbye};
    
    printf("\nUsing Action typedef:\n");
    for (int i = 0; i < 2; i++) {
        printf("  Action %d: ", i);
        actions[i]();
    }
}


/* ============================================================
 * EXAMPLE 11: Const Pointers in Function Parameters
 * ============================================================ */

// Read-only access to array
int sumArray(const int *arr, int size) {
    int sum = 0;
    for (int i = 0; i < size; i++) {
        sum += arr[i];
        // arr[i] = 0;  // ERROR: cannot modify const
    }
    return sum;
}

// Read-only string
int countVowels(const char *str) {
    int count = 0;
    while (*str) {
        char c = *str;
        if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u' ||
            c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U') {
            count++;
        }
        str++;
    }
    return count;
}

void example11_const_pointers(void) {
    printf("\n=== EXAMPLE 11: Const Pointers in Parameters ===\n\n");
    
    int numbers[] = {10, 20, 30, 40, 50};
    
    printf("Array: {10, 20, 30, 40, 50}\n");
    printf("Sum (using const int*): %d\n\n", sumArray(numbers, 5));
    
    const char *text = "Hello World";
    printf("String: \"%s\"\n", text);
    printf("Vowel count (using const char*): %d\n", countVowels(text));
    
    printf("\nBenefit: Compiler prevents accidental modification!\n");
}


/* ============================================================
 * EXAMPLE 12: Generic Swap with void Pointer
 * ============================================================ */

void genericSwap(void *a, void *b, size_t size) {
    char temp[size];  // VLA
    memcpy(temp, a, size);
    memcpy(a, b, size);
    memcpy(b, temp, size);
}

void example12_generic_swap(void) {
    printf("\n=== EXAMPLE 12: Generic Swap with void* ===\n\n");
    
    // Swap integers
    int x = 10, y = 20;
    printf("Integers before: x=%d, y=%d\n", x, y);
    genericSwap(&x, &y, sizeof(int));
    printf("Integers after:  x=%d, y=%d\n\n", x, y);
    
    // Swap doubles
    double a = 3.14, b = 2.71;
    printf("Doubles before: a=%.2f, b=%.2f\n", a, b);
    genericSwap(&a, &b, sizeof(double));
    printf("Doubles after:  a=%.2f, b=%.2f\n\n", a, b);
    
    // Swap chars
    char c1 = 'A', c2 = 'Z';
    printf("Chars before: c1='%c', c2='%c'\n", c1, c2);
    genericSwap(&c1, &c2, sizeof(char));
    printf("Chars after:  c1='%c', c2='%c'\n", c1, c2);
}


/* ============================================================
 * EXAMPLE 13: Function Returning Function Pointer
 * ============================================================ */

typedef int (*MathOp)(int, int);

MathOp getOperation(char op) {
    switch (op) {
        case '+': return add;
        case '-': return subtract;
        case '*': return multiply;
        case '/': return divide_int;
        default: return NULL;
    }
}

void example13_return_function_pointer(void) {
    printf("\n=== EXAMPLE 13: Function Returning Function Pointer ===\n\n");
    
    char operators[] = {'+', '-', '*', '/'};
    int a = 15, b = 3;
    
    printf("Calculating %d [op] %d:\n\n", a, b);
    
    for (int i = 0; i < 4; i++) {
        MathOp op = getOperation(operators[i]);
        if (op != NULL) {
            printf("  %d %c %d = %d\n", a, operators[i], b, op(a, b));
        }
    }
}


/* ============================================================
 * EXAMPLE 14: Menu System with Function Pointers
 * ============================================================ */

void menuOption1(void) { printf("  โ†’ Executing Option 1: File operations\n"); }
void menuOption2(void) { printf("  โ†’ Executing Option 2: Edit operations\n"); }
void menuOption3(void) { printf("  โ†’ Executing Option 3: View operations\n"); }
void menuOption4(void) { printf("  โ†’ Executing Option 4: Help\n"); }

typedef void (*MenuHandler)(void);

void example14_menu_system(void) {
    printf("\n=== EXAMPLE 14: Menu System with Function Pointers ===\n\n");
    
    MenuHandler handlers[] = {menuOption1, menuOption2, menuOption3, menuOption4};
    const char *menuItems[] = {"File", "Edit", "View", "Help"};
    
    printf("Menu:\n");
    printf("โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n");
    for (int i = 0; i < 4; i++) {
        printf("%d. %s\n", i + 1, menuItems[i]);
    }
    printf("โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n\n");
    
    printf("Simulating menu selections:\n");
    for (int choice = 0; choice < 4; choice++) {
        printf("Selected: %s\n", menuItems[choice]);
        handlers[choice]();
        printf("\n");
    }
}


/* ============================================================
 * EXAMPLE 15: Passing Function Pointer as Parameter
 * ============================================================ */

int* transform(int *arr, int size, int (*transformer)(int)) {
    int *result = (int*)malloc(size * sizeof(int));
    if (result == NULL) return NULL;
    
    for (int i = 0; i < size; i++) {
        result[i] = transformer(arr[i]);
    }
    return result;
}

int square(int x) { return x * x; }
int cube(int x) { return x * x * x; }
int negate(int x) { return -x; }

void example15_function_as_parameter(void) {
    printf("\n=== EXAMPLE 15: Function Pointer as Parameter ===\n\n");
    
    int arr[] = {1, 2, 3, 4, 5};
    int size = 5;
    
    printf("Original array: ");
    for (int i = 0; i < size; i++) printf("%d ", arr[i]);
    printf("\n\n");
    
    // Transform with square
    int *squared = transform(arr, size, square);
    printf("Squared:  ");
    for (int i = 0; i < size; i++) printf("%d ", squared[i]);
    printf("\n");
    free(squared);
    
    // Transform with cube
    int *cubed = transform(arr, size, cube);
    printf("Cubed:    ");
    for (int i = 0; i < size; i++) printf("%d ", cubed[i]);
    printf("\n");
    free(cubed);
    
    // Transform with negate
    int *negated = transform(arr, size, negate);
    printf("Negated:  ");
    for (int i = 0; i < size; i++) printf("%d ", negated[i]);
    printf("\n");
    free(negated);
}


/* ============================================================
 * MAIN FUNCTION
 * ============================================================ */

int main() {
    printf("โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—\n");
    printf("โ•‘          POINTERS AND FUNCTIONS - EXAMPLES                   โ•‘\n");
    printf("โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•\n");
    
    example1_value_vs_reference();
    example2_swap();
    example3_modify_array();
    example4_return_pointers();
    example5_multiple_return_values();
    example6_function_pointers();
    example7_function_pointer_array();
    example8_callbacks();
    example9_sort_callback();
    example10_typedef_function_pointers();
    example11_const_pointers();
    example12_generic_swap();
    example13_return_function_pointer();
    example14_menu_system();
    example15_function_as_parameter();
    
    printf("\nโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•\n");
    printf("                    All examples completed!                     \n");
    printf("โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•\n");
    
    return 0;
}
Examples - C Programming Tutorial | DeepML