Passing Variables to Functions in C: A Beginner’s Guide

Learn how to effectively pass variables to functions in C programming with this beginner-friendly guide. Explore the differences between passing by value and passing by address, complete with clear examples and practical tips. Master function parameters to enhance your coding skills and write more efficient C programs!
code
c
Author

Steven P. Sanderson II, MPH

Published

April 23, 2025

Keywords

Programming, C Function Parameters, Passing Variables in C, C Programming Functions, Function Arguments C, C Parameter Passing Methods, Pass by Value C, Pass by Address C, C Function Examples, Array Parameters C, C Variable Scope Functions, How to pass multiple variables to functions in C, Difference between pass by value and address with examples, When to use passing by address vs passing by value C, Common mistakes passing variables to C functions, C programming function parameter best practices

Author’s Note: I am learning as I write this series, so I hope you find these explanations helpful and easy to understand as we explore C programming together!

Are you struggling to understand how variables are passed to functions in C? You’re not alone! One of the most fundamental yet challenging concepts for beginner C programmers is understanding the difference between passing variables by value and by address. In this comprehensive guide, we’ll break down these concepts with clear explanations and working code examples that you can try yourself.

What You’ll Learn

In this article, we’ll cover:

  • The two main methods of passing variables to functions: by value and by address
  • How memory works when passing variables
  • Working code examples with step-by-step explanations
  • Common pitfalls and how to avoid them
  • Best practices for when to use each method

Let’s go!


Understanding Variable Passing in C

In C programming, functions can share local variables by passing them between functions. This is essential for creating modular, reusable code. There are two primary ways to pass variables to functions:

  1. Passing by value (also called “passing by copy”)
  2. Passing by address (often referred to as “passing by reference”)

Understanding the difference between these two methods is crucial for writing effective C programs.


Passing Variables by Value

What is Passing by Value?

When you pass a variable by value, the function receives a copy of the original variable’s value. This means any changes made to the variable inside the function will not affect the original variable in the calling function.

Key Point: Passing by value is the default method for all non-array variables in C.

How Passing by Value Works

Let’s look at a simple example:

#include <stdio.h>

// Function that attempts to modify its parameter
void modifyValue(int x) {
    x = x * 2;    // This modification only affects the local copy
    printf("Inside function: x = %d\n", x);
}

int main() {
    int num = 5;
    printf("Before function call: num = %d\n", num);
    modifyValue(num);
    printf("After function call: num = %d\n", num);
    return 0;
}

Expected Output:

Before function call: num = 5
Inside function: x = 10
After function call: num = 5

What’s Happening in Memory?

When we pass num to the modifyValue function, here’s what happens:

  1. The value of num (which is 5) is copied to the parameter x.
  2. Inside the function, x is multiplied by 2, becoming 10.
  3. When the function ends, the copy (x) is destroyed.
  4. The original num variable remains unchanged at 5.

Think of it like giving someone a photocopy of a document — they can write all over their copy, but your original document stays intact.


Passing Variables by Address

What is Passing by Address?

Passing by address means sending the memory address of the variable to the function. This allows the function to directly access and modify the original variable.

Key Point: For passing non-array variables by address, you must use the & (address-of) operator when passing the variable.

How Passing by Address Works

Let’s see this in action:

#include <stdio.h>

// Function that modifies the value at the address it receives
void modifyValue(int *x) {
    *x = *x * 2;    // This modification affects the original variable
    printf("Inside function: *x = %d\n", *x);
}

int main() {
    int num = 5;
    printf("Before function call: num = %d\n", num);
    modifyValue(&num);    // Pass the address of num
    printf("After function call: num = %d\n", num);
    return 0;
}

Expected Output:

Before function call: num = 5
Inside function: *x = 10
After function call: num = 10

What’s Happening in Memory?

When we pass &num to the modifyValue function:

  1. The memory address of num is passed to the function.
  2. Inside the function, x is a pointer that stores this address.
  3. The expression *x accesses the value stored at that address.
  4. When we modify *x, we’re directly changing the value of num.

This is like giving someone directions to your house instead of a photocopy — they can now come to your house and rearrange your furniture!


Working with Multiple Parameters

You can pass multiple parameters to a function, mixing both passing by value and passing by address methods:

#include <stdio.h>

// Function that demonstrates both pass by value and pass by address
void updateValues(int *a, int b) {
    *a = *a + b;    // Modifies the original variable
    b = b * 2;      // Only modifies the local copy
    printf("Inside function: *a = %d, b = %d\n", *a, b);
}

int main() {
    int x = 5, y = 10;
    printf("Before function call: x = %d, y = %d\n", x, y);
    updateValues(&x, y);
    printf("After function call: x = %d, y = %d\n", x, y);
    return 0;
}

Expected Output:

Before function call: x = 5, y = 10
Inside function: *a = 15, b = 20
After function call: x = 15, y = 10

What’s Happening Here?

  1. x is passed by address (&x), so changes to *a affect the original variable.
  2. y is passed by value, so changes to b do not affect the original variable.
  3. The result is that x is updated to 15, but y remains 10.

Arrays and Function Parameters

When passing arrays to functions in C, they are always passed by address by default. You don’t need to use the & operator when passing an array.

Let’s see an example:

#include <stdio.h>

void modifyArray(int arr[], int size) {
    for (int i = 0; i < size; i++) {
        arr[i] = arr[i] * 2;  // This will modify the original array
    }
}

int main() {
    int numbers[] = {1, 2, 3, 4, 5};
    int size = sizeof(numbers) / sizeof(numbers[0]);
    
    printf("Before function call:\n");
    for (int i = 0; i < size; i++) {
        printf("%d ", numbers[i]);
    }
    
    modifyArray(numbers, size);  // No & operator needed
    
    printf("\nAfter function call:\n");
    for (int i = 0; i < size; i++) {
        printf("%d ", numbers[i]);
    }
    
    return 0;
}

Expected Output:

Before function call:
1 2 3 4 5
After function call:
2 4 6 8 10

Why Are Arrays Different?

In C, the name of an array (numbers in our example) is actually a pointer to the first element of the array. This is why arrays are automatically passed by address and why changes made inside the function affect the original array.


Common Pitfalls and Mistakes

1. Forgetting to Use the Address Operator (&)

void half(int *i) {
    *i = *i / 2;
}

int main() {
    int num = 10;
    half(num);  // ERROR: Expected pointer type
    return 0;
}

Correct Version:

half(&num);  // Pass the address

2. Dereferencing Errors

void half(int *i) {
    *i = i / 2;  // ERROR: Trying to divide a pointer by 2
}

Correct Version:

*i = *i / 2;  // Dereference the pointer to get the value

3. Trying to Pass Arrays by Value

C does not support passing arrays by value. Arrays are always passed by address.

4. Modifying Variables Unintentionally

Make sure you’re passing by value when you want to protect the original data and by address only when you need to modify the original variable.


Passing Variables to Functions in C: By Value vs. By Address

When writing C programs, functions are the building blocks for organizing code and reusing logic. However, how you pass variables to these functions can significantly affect your program’s behavior and performance. One of the most important decisions you’ll make when designing C functions is how you’ll pass variables to them. Should you pass a copy of your data or share access to the original variable? Let’s break down these two approaches to help you make the right choice for your programs.

Side-by-Side Comparison

Understanding the differences between these two approaches is crucial for writing effective C programs. Here’s a side-by-side comparison:

Aspect Passing by Value Passing by Address
Data Copied? Yes – A copy of the variable is sent. No – Only the memory address is sent.
Original Variable Affected? No – Changes affect only the local copy. Yes – Changes update the original variable.
Safety: Safer, as it prevents accidental modification. Riskier if not handled properly (e.g., null pointers).
Best For: When you want to use data without modifying it. When the function needs to update the original data.
Usage Examples: Basic data manipulations (e.g., mathematical operations). Modifying arrays, updating counters, or handling large data structures.

When to Use Which Method

Pass by Value When:

  • You need to protect the data from unintentional modifications. For example, if you have an important counter or constant value that should remain unchanged, passing by value is a safe option.
  • You’re working with small data types like integers, characters, or floating-point numbers where the copying overhead is minimal.
  • You want to maintain function independence – ensuring that your function doesn’t create side effects by modifying variables outside its scope.

Pass by Address When:

  • You want the function to modify the original variable. This method is particularly useful with arrays or when working with dynamic data structures that need to be updated throughout the program.
  • You’re dealing with large data structures and want to avoid the performance overhead of copying large amounts of data.
  • You need to return multiple values from a function (since C functions can only have one return value, passing by address allows you to update multiple variables).

Visual Explanation

Let’s visualize the difference with a simple example:

// Passing by Value
void doubleValue(int x) {      // ┌───┐
    x = x * 2;                 // │ 5 │ <- Copy of num created here
}                              // └───┘
                               
int main() {                   // ┌───┐
    int num = 5;               // │ 5 │ <- Original value remains unchanged
    doubleValue(num);          // └───┘
    // num is still 5
}

// Passing by Address
void doubleValue(int *x) {     // ┌───┐
    *x = *x * 2;               // │ * │ <- Points to original num
}                              // └─┬─┘
                                   │
int main() {                   // ┌─▼─┐
    int num = 5;               // │ 5 │ <- Gets modified to 10
    doubleValue(&num);         // └───┘
    // num is now 10
}

Best Practices

To write clear and maintainable code:

  1. Be consistent with your parameter passing style within related functions.

  2. Use comments to indicate which parameters are expected to be modified (when passing by address).

  3. Consider using const for pointer parameters when you don’t intend to modify the pointed data:

    void printArray(const int *arr, int size);  // Signals that arr won't be modified
  4. Always check for NULL when working with pointers to avoid segmentation faults:

    void processData(int *data) {
        if (data == NULL) return;  // Safety check
        // Process data here
    }

Performance Considerations

For small data types (like int, char, or float), the performance difference between passing by value and passing by address is negligible on modern systems. However, for larger structures, passing by address can significantly improve performance by avoiding unnecessary copying.

Key Takeaway: Choose passing by value when you want to protect data from changes. Choose passing by address when you need to modify the original data or when working with large data structures.

By understanding both methods and when to apply each one, you’ll be able to write more efficient, safer, and more maintainable C code.


Your Turn!

Let’s practice what we’ve learned:

Try to predict what the following code will output:

#include <stdio.h>

void mystery(int *x, int y) {
    *x = *x + 5;
    y = y + 5;
    printf("Inside function: *x = %d, y = %d\n", *x, y);
}

int main() {
    int a = 10, b = 20;
    mystery(&a, b);
    printf("After function: a = %d, b = %d\n", a, b);
    return 0;
}
See Solution
Inside function: *x = 15, y = 25
After function: a = 15, b = 20

Explanation:

  • a is passed by address, so the change to *x modifies the original value.
  • b is passed by value, so the change to y does not affect the original value.

Key Takeaways

  • Passing by value creates a copy of the variable, and modifications don’t affect the original variable.
  • Passing by address shares the memory location, allowing functions to modify the original variable.
  • Use the & operator to pass a non-array variable by address.
  • Use the * operator to access and modify the value at an address (dereferencing).
  • Arrays are always passed by address in C, without needing the & operator.
  • Choose the appropriate passing method based on whether you need to modify the original variables.

Conclusion

Understanding how to pass variables to functions is a fundamental skill for C programmers. By mastering the concepts of passing by value and passing by address, you’ll be able to write more efficient and effective code.

Remember:

  • Pass by value when you want to protect your data
  • Pass by address when you need to modify the original variable
  • Arrays are always passed by address

What other C programming concepts would you like to learn more about? Let me know in the comments section below!


Frequently Asked Questions

Q: Can I pass an array by value in C?

A: No, arrays in C are always passed by address. You cannot pass an entire array by value. If you need a copy, you must create one manually inside the function.

Q: What’s the difference between “pass by reference” and “pass by address”?

A: Technically, C only supports pass by value and pass by address. “Pass by reference” is a term often borrowed from other languages. In C, we use pointers to achieve similar functionality, which is why we call it “pass by address.”

Q: How do I return multiple values from a function in C?

A: Since C functions can only return one value, you can use the pass by address method to modify multiple variables inside the function.

Q: What happens if I forget to dereference a pointer?

A: If you forget to dereference a pointer (using the * operator), you’ll be working with the memory address itself rather than the value stored at that address, which can lead to unexpected behavior or errors.

Q: Is passing by address more efficient than passing by value?

A: For small data types like integers, the difference is negligible. For large data structures, passing by address is more efficient because it avoids copying large amounts of data.


References

  1. Parameter Passing Techniques in C - GeeksforGeeks
  2. Passing by Value vs Reference Visual Explanation
  3. C Functions - cppreference.com
  4. C Programming Documentation - Microsoft Learn

Did you find this article helpful? Share it with your fellow programmers who are learning C! If you have any questions or would like to see more examples, leave a comment below.


Happy Coding! 🚀

Passing Variables in C

You can connect with me at any one of the below:

Telegram Channel here: https://t.me/steveondata

LinkedIn Network here: https://www.linkedin.com/in/spsanderson/

Mastadon Social here: https://mstdn.social/@stevensanderson

RStats Network here: https://rstats.me/@spsanderson

GitHub Network here: https://github.com/spsanderson

Bluesky Network here: https://bsky.app/profile/spsanderson.com

My Book: Extending Excel with Python and R here: https://packt.link/oTyZJ

You.com Referral Link: https://you.com/join/EHSLDTL6