Docs

Parameters and Arguments

Function Parameters and Arguments

šŸ“– Introduction

Parameters allow functions to receive data from the caller. Understanding how parameters work in C is crucial because C uses pass by value by default, meaning functions receive copies of arguments. This section covers all aspects of function parameters.


šŸŽÆ Parameters vs Arguments

ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
│ Function Definition:                                        │
│                                                              │
│   int add(int a, int b)  ◄─── Parameters (Formal)           │
│   {                            - a and b are parameters     │
│       return a + b;            - Variables in definition    │
│   }                                                          │
ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜

ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
│ Function Call:                                               │
│                                                              │
│   int x = 5, y = 10;                                        │
│   int sum = add(x, y);  ◄─── Arguments (Actual)             │
│                              - x and y are arguments        │
│                              - Values passed to function    │
ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜

šŸ“¤ Pass by Value

C passes arguments by value, meaning a copy is made.

How It Works:

void modify(int n) {
    n = n * 2;  // Modifies COPY, not original
    printf("Inside: %d\n", n);
}

int main() {
    int x = 10;
    modify(x);
    printf("Outside: %d\n", x);  // Still 10!
    return 0;
}

Memory Diagram:

Before call:              During call:              After call:
ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”          ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”          ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
│ main()      │          │ main()      │          │ main()      │
│  x = 10     │          │  x = 10     │          │  x = 10     │
ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜          ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜          ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜
                         ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
                         │ modify()    │
                         │  n = 10     │ ─► n = 20
                         │  (copy!)    │
                         ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜

Implications:

OperationOriginal VariableLocal Copy
ReadSafeHas same value
ModifyNot affectedOnly copy changes
ReturnUnchangedDestroyed after function

šŸ“Š Different Parameter Types

1. Basic Types:

void printValues(int i, float f, double d, char c) {
    printf("int: %d\n", i);
    printf("float: %f\n", f);
    printf("double: %lf\n", d);
    printf("char: %c\n", c);
}

// Call:
printValues(42, 3.14f, 2.71828, 'A');

2. Array Parameters:

Arrays are special - they decay to pointers!

// These are equivalent:
void printArray(int arr[], int size);
void printArray(int *arr, int size);

void printArray(int arr[], int size) {
    for (int i = 0; i < size; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
}

// Call:
int numbers[] = {1, 2, 3, 4, 5};
printArray(numbers, 5);

Important: Modifying array elements affects the original!

void doubleElements(int arr[], int size) {
    for (int i = 0; i < size; i++) {
        arr[i] *= 2;  // Modifies original array!
    }
}

3. String Parameters:

Strings are char arrays, so they also decay to pointers:

void printString(char str[]) {
    printf("%s\n", str);
}

// or equivalently:
void printString(char *str) {
    printf("%s\n", str);
}

// Call:
printString("Hello, World!");

4. 2D Array Parameters:

Must specify second dimension:

// Must specify columns
void printMatrix(int matrix[][3], int rows) {
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < 3; j++) {
            printf("%d ", matrix[i][j]);
        }
        printf("\n");
    }
}

// Call:
int matrix[2][3] = {{1, 2, 3}, {4, 5, 6}};
printMatrix(matrix, 2);

šŸ”§ const Parameters

Use const to prevent modification:

For Basic Types:

void printNumber(const int n) {
    // n = 10;  // Error! Cannot modify const
    printf("%d\n", n);
}

For Pointers/Arrays:

// Pointer to const data - cannot modify what it points to
void printArray(const int arr[], int size) {
    for (int i = 0; i < size; i++) {
        // arr[i] = 0;  // Error! Cannot modify
        printf("%d ", arr[i]);
    }
}

// Const pointer to const data - cannot modify pointer or data
void printString(const char *const str) {
    // *str = 'X';   // Error!
    // str = NULL;   // Error!
    printf("%s\n", str);
}

šŸ“„ Default Values

C does NOT support default parameter values like C++!

// This does NOT work in C:
// void greet(char* name = "World") { ... }

// Workaround using wrapper function:
void greetWithName(char* name) {
    printf("Hello, %s!\n", name);
}

void greet() {
    greetWithName("World");  // Default
}

šŸ”¢ Variable Number of Arguments

C supports variadic functions using <stdarg.h>:

Basic Structure:

#include <stdarg.h>

int sum(int count, ...) {
    va_list args;
    va_start(args, count);

    int total = 0;
    for (int i = 0; i < count; i++) {
        total += va_arg(args, int);
    }

    va_end(args);
    return total;
}

// Call:
int result = sum(4, 10, 20, 30, 40);  // result = 100

Key Macros:

MacroPurpose
va_listType for argument list
va_start(ap, last)Initialize argument list
va_arg(ap, type)Get next argument of type
va_end(ap)Clean up

Example - printf-like function:

#include <stdarg.h>

void customPrint(const char *format, ...) {
    va_list args;
    va_start(args, format);

    while (*format != '\0') {
        if (*format == '%') {
            format++;
            switch (*format) {
                case 'd':
                    printf("%d", va_arg(args, int));
                    break;
                case 'f':
                    printf("%f", va_arg(args, double));
                    break;
                case 's':
                    printf("%s", va_arg(args, char*));
                    break;
                case '%':
                    printf("%%");
                    break;
            }
        } else {
            putchar(*format);
        }
        format++;
    }

    va_end(args);
}

šŸ“ Parameter Passing Summary

ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
│                    PARAMETER PASSING IN C                        │
ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¤
│                                                                  │
│  Basic Types (int, float, char)                                 │
│  ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”                │
│  │ Pass by Value: COPY is made                  │                │
│  │ Original cannot be modified                  │                │
│  ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜                │
│                                                                  │
│  Arrays                                                          │
│  ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”                │
│  │ Decay to pointers: ADDRESS is passed         │                │
│  │ Elements CAN be modified                     │                │
│  │ Size NOT passed automatically               │                │
│  ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜                │
│                                                                  │
│  Pointers                                                        │
│  ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”                │
│  │ Pass by Value (of address)                   │                │
│  │ Can modify what pointer points to            │                │
│  │ Cannot change original pointer itself        │                │
│  ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜                │
│                                                                  │
│  Structs                                                         │
│  ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”                │
│  │ Pass by Value: Entire struct COPIED          │                │
│  │ Expensive for large structs                  │                │
│  │ Pass pointer for efficiency                  │                │
│  ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜                │
│                                                                  │
ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜

šŸ”„ Simulating Pass by Reference

To modify the original variable, pass its address:

void swap(int *a, int *b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}

int main() {
    int x = 10, y = 20;
    printf("Before: x=%d, y=%d\n", x, y);
    swap(&x, &y);  // Pass addresses
    printf("After: x=%d, y=%d\n", x, y);
    return 0;
}
// Output:
// Before: x=10, y=20
// After: x=20, y=10

šŸ“‹ Parameter Order Best Practices

Recommended Order:

  1. •Output parameters first (pointers to results)
  2. •Input parameters next
  3. •Optional/configuration parameters last
// Example following convention:
int readData(
    int *result,           // Output
    const char *filename,  // Input
    int maxSize            // Configuration
);

Naming Conventions:

// Good - descriptive names
void copyString(char *destination, const char *source, int maxLength);

// Bad - unclear abbreviations
void cpyStr(char *d, const char *s, int m);

āš ļø Common Mistakes

1. Forgetting Array Size:

// Wrong - no way to know array size
void processArray(int arr[]) {
    // How many elements?
}

// Correct - pass size
void processArray(int arr[], int size) {
    for (int i = 0; i < size; i++) {
        // process arr[i]
    }
}

2. Returning Pointer to Local:

// WRONG! Undefined behavior
int* createNumber() {
    int n = 42;
    return &n;  // n is destroyed after return!
}

// Correct - use dynamic allocation
int* createNumber() {
    int *n = malloc(sizeof(int));
    *n = 42;
    return n;  // Caller must free()
}

3. Type Mismatch:

void printDouble(double d) {
    printf("%f\n", d);
}

int main() {
    int x = 10;
    printDouble(x);  // OK - implicit conversion

    // But be careful with pointers:
    int *pi = &x;
    // printDouble(*pi);  // This works
    // printDouble(pi);   // Warning! Wrong type
    return 0;
}

šŸ”‘ Key Takeaways

  1. •C uses pass by value - copies are made
  2. •Arrays decay to pointers - elements can be modified
  3. •Use const for read-only parameters
  4. •Pass pointers to modify original variables
  5. •Always pass array size as separate parameter
  6. •Structs are copied entirely - use pointers for large ones
  7. •Use stdarg.h for variable arguments

ā­ļø Next Topic

Continue to Recursion to learn about functions that call themselves.

Parameters And Arguments - C Programming Tutorial | DeepML