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:
- Passing by value (also called “passing by copy”)
- 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 = 5What’s Happening in Memory?
When we pass num to the modifyValue function, here’s what happens:
- The value of num(which is 5) is copied to the parameterx.
- Inside the function, xis multiplied by 2, becoming 10.
- When the function ends, the copy (x) is destroyed.
- The original numvariable 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 = 10What’s Happening in Memory?
When we pass &num to the modifyValue function:
- The memory address of numis passed to the function.
- Inside the function, xis a pointer that stores this address.
- The expression *xaccesses the value stored at that address.
- When we modify *x, we’re directly changing the value ofnum.
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 = 10What’s Happening Here?
- xis passed by address (- &x), so changes to- *aaffect the original variable.
- yis passed by value, so changes to- bdo not affect the original variable.
- The result is that xis updated to 15, butyremains 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 10Why 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 address2. 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 value3. 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:
- Be consistent with your parameter passing style within related functions. 
- Use comments to indicate which parameters are expected to be modified (when passing by address). 
- Consider using - constfor 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
- 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 = 20Explanation:
- ais passed by address, so the change to- *xmodifies the original value.
- bis passed by value, so the change to- ydoes 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
- Parameter Passing Techniques in C - GeeksforGeeks
- Passing by Value vs Reference Visual Explanation
- C Functions - cppreference.com
- 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! 🚀

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