C Pass-by-Reference (Pointer) Basics & Value-Pass Differences

1. Why You Should Learn “Pass-by-Reference”?

When learning C, the concept of “pass-by-reference (pointer passing)” is unavoidable. It’s a point where many beginners stumble, but a solid understanding equips you with the essence of C and the power of flexible programming. There are several reasons why pass-by-reference is important. First, in C, arguments are passed to functions primarily by “value”. This means the caller’s variable value is copied and passed to the function. Consequently, changing that value inside the function does not affect the caller’s variable. While this seems safe at first glance, there are many situations where you actually want to modify the caller’s value directly from within the function. For example, a swap function that exchanges two values or a routine that updates multiple values at once cannot be achieved with value passing alone. In such cases, pass-by-reference—i.e., passing arguments via pointers—comes into play. By using pointers, a function can reference the caller’s variable address and modify its value directly. Moreover, pass-by-reference is useful not only for updating simple values but also for efficiently handling large data such as arrays or structs. With value passing, each function call copies the data, which can be inefficient in terms of memory and speed. Passing a pointer eliminates the copying overhead and can improve overall program performance. By understanding and applying the mechanics of pass-by-reference in C, you can write more practical and efficient code. While it may seem daunting at first for beginners, repeated study and practice will steadily build your skill.

2. Differences Between Pass-by-Value and Pass-by-Reference

C functions have two ways to pass arguments: “pass‑by‑value” and “pass‑by‑reference (pointer passing)”. Understanding the mechanisms and characteristics of each is the first step toward reducing bugs and making code behave as intended.

What Is Pass‑by‑Value

Pass‑by‑value (call by value) is a method where, when calling a function, the “value” of the passed variable is copied to the function’s parameter. For example, see the following code.
void func(int x) {
    x = 10;
}

int main() {
    int a = 5;
    func(a);
    printf("%dn", a); // output is 5
}
In this case, the value of a (5) is copied to x in the func function. Changing x inside the function does not affect a in the main function at all. This can be understood as “the original variable remains unchanged” and “only the copy is being manipulated”.

What Is Pass‑by‑Reference (Pointer Passing)

On the other hand, pass‑by‑reference (call by reference) passes the variable’s “address (location)”. C does not have a built‑in reference type, but you can achieve the same effect using pointers. For example, consider the following example.
void func(int *x) {
    *x = 10;
}

int main() {
    int a = 5;
    func(&a);
    printf("%dn", a); // output is 10
}
The important point here is that func(&a); passes the address (location) of variable a. On the func side, writing *x accesses the “real a” that the address points to directly, allowing its value to be changed.

Summary of Differences Between Pass‑by‑Value and Pass‑by‑Reference

MethodWhat Is PassedChanges Inside FunctionEffect on Caller
Pass‑by‑valueValue (copy)Not reflectedNone
Pass‑by‑referenceAddressReflectedYes
Also, remember the rule in C: “to pass by reference, declare the parameter as a pointer type and use the address operator (&) when calling”. Understanding this difference makes function design and bug fixing much easier. In particular, when you “want to change a value inside a function” or “handle large data efficiently”, pass‑by‑reference (pointer passing) is essential.
年収訴求

3. Understanding Through Code! Three Practical Examples

Here, we explain the concrete usage of “pass-by-reference (pointer passing)” in C language with three examples. Through the code, you’ll experience the differences in behavior and the benefits.

1. Basic Pass-by-Reference Example

First, a basic example of using a pointer to modify a variable’s value from within a function.
void increment(int *p) {
    (*p)++;
}

int main() {
    int a = 0;
    increment(&a);
    printf("%dn", a); // Output: 1
    return 0;
}
In this example, the increment function receives the address as an int *p argument. By doing (*p)++, the caller’s variable a is directly modified inside the function. This is the basics of pass-by-reference.

2. swap Function Implementation Example

If you want to swap the values of two variables, you can’t do it with pass-by-value, but with pass-by-reference (pointer passing) it’s straightforward.
void swap(int *x, int *y) {
    int temp = *x;
    *x = *y;
    *y = temp;
}

int main() {
    int a = 3, b = 7;
    swap(&a, &b);
    printf("a = %d, b = %dn", a, b); // Output: a = 7, b = 3
    return 0;
}
The swap function takes two integer pointers and swaps their contents. Passing the addresses &a, &b at the call site is the key.

3. Arrays and Pass-by-Reference

In C, passing an array name to a function passes its starting address (pointer) directly. This is effectively pass-by-reference.
void fill_zero(int arr[], int size) {
    for (int i = 0; i < size; i++) {
        arr[i] = 0;
    }
}

int main() {
    int data[5] = {1, 2, 3, 4, 5};
    fill_zero(data, 5);
    for (int i = 0; i < 5; i++) {
        printf("%d ", data[i]);
    }
    // Output: 0 0 0 0 0
    return 0;
}
In this case as well, the fill_zero function can directly modify the contents of the data array. This is another example of C’s pass-by-reference. Thus, pass-by-reference is very useful when you want to manipulate values directly through a function or handle large data such as arrays efficiently. Seeing it work in real code makes its convenience clear.

4. Why Use Pass-by-Reference? Benefits and Cautions

Pass-by-reference (pointer passing) is an important technique for writing more flexible and efficient programs in C. Here we explain the main benefits of using pass-by-reference and the points to watch out for when using it.

Benefits of Pass-by-Reference

  1. You can directly modify caller’s value from a function With pass-by-value, changes to values inside a function do not affect the caller, but with pass-by-reference you can modify the variable itself that was passed as an argument. For example, it’s useful in situations like a swap function or adding/subtracting values where you want to return results in a form other than the return value.
  2. Efficient handling of large data When passing large data such as arrays or structs to a function, pass-by-value copies everything, leading to unnecessary memory consumption and slower performance. With pass-by-reference (pointer passing), only the address (location) is passed, eliminating copy overhead and making it efficient.
  3. Can modify multiple values simultaneously With pass-by-value you can return only one value, but using pass-by-reference you can change the values of multiple variables at once. This greatly expands a function’s flexibility.

Cautions and Drawbacks of Pass-by-Reference

  1. Side effects are easy to occur Because you can directly modify the caller’s data, it can become hard to know where a value was changed in the program. In large codebases or team development, this can lead to unexpected bugs, so caution is required.
  2. Bugs caused by mishandling pointers If you don’t manage addresses (pointers) correctly, unexpected problems arise. For example, accidentally dereferencing a NULL pointer or accessing freed memory can cause crashes—hazards that are unique to C.
  3. Readability and comprehension difficulty Code that heavily uses pointers tends to be hard for beginners to understand. Also, misusing symbols like ‘&’ and ‘*’ can easily lead to unexpected behavior.
Thus, pass-by-reference is a convenient and powerful feature, but misusing it can lead to bugs and reduced maintainability. Using it correctly in the right situations is the shortcut to mastering C programming. Especially in critical or safety-sensitive code, be sure to perform thorough NULL checks and include proper documentation comments.

5. Differences with C++ (Supplement)

When learning C, the term “pass‑by‑reference” also appears in C++, which can be a confusing point. Here, we’ll briefly outline the differences in “pass‑by‑reference” between C and C++.

Pass‑by‑reference in C = Pass‑by‑pointer

In C, even though we talk about “pass‑by‑reference,” it actually uses pointers to pass a variable’s address to a function. The function uses the pointer to modify the value at that address, thereby affecting the caller’s variable.
void func(int *x) {
    *x = 100;
}
int main() {
    int a = 0;
    func(&a);
    // a becomes 100
    return 0;
}
Thus, you receive the argument as a pointer type by prefixing it with *, and when calling you must pass the address, e.g., &a.

Pass‑by‑reference in C++ is simpler

In contrast, C++ provides a built‑in “reference” type as part of the language. By using & in a variable declaration, you can receive an argument as a reference, allowing the function to operate directly on the caller’s variable. Unlike pointers, references can be used just like ordinary variables without any special operators.
void func(int &x) {
    x = 100;
}
int main() {
    int a = 0;
    func(a);
    // a becomes 100
    return 0;
}
C++ references are safer and more intuitive because they eliminate the risk of forgetting to pass an address or making pointer‑related mistakes. Moreover, C++ allows you to choose between pointer passing and reference passing as appropriate for the task.

Summary: Differences in Usage

  • C: Pass‑by‑reference = using pointers (* and & required)
  • C++: Pass‑by‑reference = using reference types (& only, no pointer manipulation needed)
When you start learning C++, you’ll appreciate the convenience and safety of references, but understanding pointer manipulation in C is extremely helpful for grasping low‑level behavior. C++ references also rely on address mechanisms under the hood, so a solid C foundation translates into stronger applied skills. Being aware of these differences will enable you to switch between C and C++ more smoothly.

6. FAQ Frequently Asked Questions

Here we summarize, in a Q&A format, the points that learners often wonder about regarding “C language pass‑by‑reference”. Let’s clear up the common confusions and real‑world stumbling blocks.

Question 1: Why does passing an array to a function in C result in pass‑by‑reference?

In C, when you pass an array name to a function, the array’s starting address (a pointer) is automatically passed. Therefore, if the function modifies an element of the array, the change is reflected in the caller’s array. It’s not a true value‑pass; you can think of it as effectively pass‑by‑reference (pointer passing).

Question 2: What happens if you modify the pointer’s value (the address) itself inside a function?

Changing the value of the pointer variable itself (i.e., the address it points to) inside the function does not affect the caller’s pointer. If you need to modify the caller’s pointer variable, you must use a pointer to a pointer (a double pointer).

Question 3: Can structs also be passed by reference?

Yes, structs can be passed by reference by passing a pointer to the function. Passing by value copies the entire struct, whereas passing a pointer lets you handle the data efficiently.
struct Data {
    int value;
};

void update(struct Data *d) {
    d->value = 123;
}

Question 4: What safety measures are needed when using pass‑by‑reference?

When using pointers, it’s important to perform NULL checks and verify that an address is valid. If you dereference an invalid address, the program can crash, so include checks such as if (ptr != NULL) inside functions. Also, memory allocated with malloc should be freed at the appropriate time.

Question 5: When choosing between C and C++ for pass‑by‑reference, which should you pick?

In C, you achieve pass‑by‑reference with pointers, whereas C++ provides reference types (e.g., int &x) that are generally preferred for readability and safety. However, low‑level control and inter‑language interfacing still require a solid understanding of C pointers. Choose based on your goals and project requirements.

Question 6: I’m not good with pointers. Any tips?

First, clearly organize in your mind the roles of variable names, the address operator (&), and the dereference operator (*). Writing simple code and visually confirming the relationship between variables, addresses, and pointers deepens understanding. Sketching diagrams on paper is also helpful. Use this FAQ to further deepen your understanding of pass‑by‑reference. Whenever a question arises, look it up and try it out—hands‑on practice is the fastest way to improve.
年収訴求