GuideC Programming

Parameters And Arguments

Functions / Parameters And Arguments

Concept Lesson
Intermediate
4 min

Learning Objective

Understand Parameters And Arguments well enough to explain it, recognize it in C Programming, and apply it in a small task.

Why It Matters

This concept is part of the foundation that later lessons and projects assume you already understand.

AndParameters Vs ArgumentsPass By ValueHow It WorksMemory Diagram
Private notes
0/8000

Notes stay private to your browser until account sync is configured.

Guide
2 min read18 headings

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

  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.

Skill Check

Test this lesson

Answer 4 quick questions to lock in the lesson and feed your adaptive practice queue.

--
Score
0/4
Answered
Not attempted
Status
1

Which module does this lesson belong to?

2

Which section is covered in this lesson content?

3

Which term is most central to this lesson?

4

What is the best way to use this lesson for real learning?

Your answers save locally first, then sync when account storage is available.
Practice queue