66

In my University's C programming class, the professor and subsequent book written by her uses the term call or pass by reference when referring to pointers in C.

An example of what is considered a 'call by reference function' by my professor:

int sum(int *a, int *b);

An example of what is considered a 'call by value function' by my professor:

int sum(int a, int b);

I've read C doesn't support call by reference. To my understanding, pointers pass by value.

Basically, is it incorrect to say pointers are C's way of passing by reference? Would it be more correct to say you cannot pass by reference in C but can use pointers as an alternative?


Update 11/11/15

From the way my question originated, I believe a debate of terminology has stemmed and in fact I'm seeing two specific distinctions.

  • pass-by-reference (the term used mainly today): The specific term as used in languages like C++
  • pass-by-reference (the term used by my professor as a paradigm to explain pointers): The general term used before languages like C++ were developed and thus before the term was rewritten

After reading @Haris' updated answer it makes sense why this isn't so black and white.

Community
  • 1
  • 1
Insane
  • 889
  • 10
  • 21
  • 6
    *"Would it be more correct to say you cannot pass by reference in C but can use pointers as an alternative?"* Speaking as someone who doesn't write C but who often explains the difference between *pass-by-value* and *pass-by-reference*: yes. I find the Wikipedia article about this topic pretty good: https://en.wikipedia.org/wiki/Evaluation_strategy . – Felix Kling Nov 10 '15 at 04:20
  • 2
    C is pass by value. Pass by reference doesn't really make sense, in terms C's paradigm. – Bobby Sacamano Nov 10 '15 at 04:21
  • 1
    AFAIK, in **C++**, you *can't tell* whether you're *passing a value by reference* or *passing a reference by value*, because they'd both do exactly the same thing. That demonstrates the distinction is pretty meaningless. – user253751 Nov 10 '15 at 06:05
  • 1
    The question is about C – BobRun Nov 10 '15 at 06:49
  • 1
    Your professor is ***WROOOOOONG***. But seriously, what he/she is very likely doing is simply using a metaphor to help people with a Java background understand what's going on, but if so, he/she could probably be a little clearer about the fact that isn't a literal description of what's happening. – Panzercrisis Nov 10 '15 at 13:56
  • 1
    @Panzercrisis Yes, I came into the course from learning Java previously (which has no call by reference) and can say it did help me understand, however, I would've liked to avoid this confusion in the first place with a _proper_ explanation. – Insane Nov 10 '15 at 14:03
  • 4
    My guess is your professor learned C back when there weren't sooo many languages out there and nitpicking about the exact meaning of *pass by reference* was not an issue. Think about it: your computer's CPU doesn't support "pass by reference", that's something invented to make it easier on humans. – Roflo Nov 10 '15 at 15:09
  • 7
    @Panzercrisis "... isn't a literal description of what's happening." - I think the opposite is true: Creating a pointer to some variable and then passing that pointer around is *exactly* what calling-by-reference does in the end. So, to illustrate the difference between values and references, the C example works quite well. You have to take care of the referencing and dereferencing yourself, because the language C is call-by-value, where C++ hides that bit of boilerplate code from you in the compiler. – JimmyB Nov 10 '15 at 15:21
  • @HannoBinder Okay, yeah, I guess if it's a birds-eye view description of what's going on, rather than of the syntatical construct. – Panzercrisis Nov 10 '15 at 15:46
  • 2
    @Insane *"from learning Java previously (which has no call by reference)"* ... What happens when you mutate a passed object within a function? – brian_o Nov 10 '15 at 16:42
  • 1
    @brian_o [.But this question is about C.](http://stackoverflow.com/questions/40480/is-java-pass-by-reference-or-pass-by-value) – Insane Nov 10 '15 at 16:44
  • 1
    @insane Your final statement is essentially correct. But I also think there is merit in your professor's description of "call by reference". It may be helpful to play with a few functions where you are passing around large `struct`s and pointers to `struct`s, then you can decide for yourself if you find merit in the "call by reference" metaphor. – brian_o Nov 10 '15 at 17:01
  • @brian_o Yeah, I'll have to do that once I start working with `struct`s. The input is appreciated! – Insane Nov 10 '15 at 17:03
  • 2
    The number of programmers who really understand the difference between pass by reference and pass by value are outnumbered by those who don't by at least 10:1... There are no "shortcuts" to it, you have to look at what is actually being passed. – corsiKa Nov 10 '15 at 19:49
  • 1
    The terms "value" and "reference" are really higher-level programming terms that just don't apply to C. You can implement EVERY programming paradigm in C, just as you can in assembly--object oriented programming, functional programming, whatever--because they all have to be translated into hardware at some point. But that doesn't make those paradigms "features" of the C language. – Lee Daniel Crocker Nov 10 '15 at 23:32
  • 1
    C is strictly pass-by-value, but the value can be a pointer. – dan04 Nov 11 '15 at 05:25
  • 1
    It seems to me that all the confusion you have is in the language. What do you expect from a value passed by reference? What do you expect from a value passed by pointer? I think you'll find that the answer to both is basically the same - especially in case of a simple int pointer. Don't dwell on names too much - this isn't mathematics, there's a lot of conflicting terms for everything. – Luaan Nov 11 '15 at 13:47
  • 1
    I find the way people talk about passing by reference vs value to be grossly over-complicated. Passing by reference in C++ is extremely similar to passing a pointer in C. I would say it's the same thing, but I'm sure some pedant would refute me =]. You're passing the address of something rather than the thing its self. So, I would say that your professor is not wrong. – Sava B. Nov 11 '15 at 16:22
  • @Lee "value" certainly makes sense in C - *everything* is passed as a value in C. The C standard also uses "value" rather extensively. – Voo Nov 11 '15 at 18:40
  • @dan04 can you give an example of pass-by-reference that is not, technically, using pointers? (in any language) – miraculixx Nov 11 '15 at 19:01
  • 1
    @SavaB. Not only is passing a reference (in C++) similar to passing a pointer (in C++ or C), it's also similar to passing *by* reference! There's no clear distinction there. – user253751 Nov 12 '15 at 10:24

8 Answers8

58

you cannot pass by reference in C but can use pointers as an alternative

Yup, thats correct.


To elaborate a little more. Whatever you pass as an argument to c functions, it is passed by values only. Whether it be a variable's value or the variable address.

What makes the difference is what you are sending.

When we pass-by-value we are passing the value of the variable to a function. When we pass-by-reference we are passing an alias of the variable to a function. C can pass a pointer into a function but that is still pass-by-value. It is copying the value of the pointer, the address, into the function.


  • If you are sending the value of a variable, then only the value will be received by the function, and changing that won't effect the original value.

  • If you are sending the address of a variable, then also only the value(the address in this case) is sent, but since you have the address of a variable it can be used to change the original value.


As an example, we can see some C++ code to understand the real difference between call-by-value and call-by-reference. Taken from this website.

// Program to sort two numbers using call by reference. 
// Smallest number is output first.

#include <iostream>
using namespace std;

// Function prototype for call by reference
void swap(float &x, float &y);

int main()
{
   float a, b;

   cout << "Enter 2 numbers: " << endl;
   cin >> a >> b;
   if(a>b) 
     swap(a,b); // This looks just like a call-by-value, but in fact
                // it's a call by reference (because of the "&" in the
                // function prototype

   // Variable a contains value of smallest number
   cout << "Sorted numbers: ";
   cout << a << " " << b << endl;
   return 0;
}

// A function definition for call by reference
// The variables x and y will have their values changed.

void swap(float &x, float &y)
// Swaps x and y data of calling function
{
   float temp;

   temp = x;
   x = y;
   y = temp;
}

In this C++ example, reference variable(which is not present in C) is being used. To quote this website,

"A reference is an alias, or an alternate name to an existing variable...",

and

"The main use of references is acting as function formal parameters to support pass-by-reference..."

This is different then the use of pointers as function parameters because,

"A pointer variable (or pointer in short) is basically the same as the other variables, which can store a piece of data. Unlike normal variable which stores a value (such as an int, a double, a char), a pointer stores a memory address."

So, essentially when one is sending address and receiving through pointers, one is sending the value only, but when one is sending/receiving a reference variable, one is sending an alias, or a reference.


**UPDATE : 11 November, 2015**

There has been a long debate in the C Chatroom, and after reading comments and answers to this question, i have realized that there can be another way to look at this question, another perspective that is.

Lets look at some simple C code

int i;
int *p = &i;
*p = 123;

In this scenario, one can use the terminology that, p's value is a reference to i. So, if that is the case, then if we send the same pointer (int* p) to a function, one can argue that, since i's reference is sent to the function, and thus this can be called pass-by-reference.

So, its a matter of terminology and way of looking at the scenario.

I would not completely disagree with that argument. But for a person who completely follows the book and rules, this would be wrong.


NOTE: Update inspired by this chat.

Community
  • 1
  • 1
Haris
  • 12,120
  • 6
  • 43
  • 70
  • 7
    In that case I would say it's quite misleading to explain pass-by-reference using pointers and also never explicitly say pointers still pass-by-value in C. – Insane Nov 10 '15 at 04:24
  • 1
    @Insane, yup. i have seen college professors explaining that way. I also was mislead in the beginning, but later i understood. – Haris Nov 10 '15 at 04:26
  • 4
    Not only some professors, but some books also address it as pass by reference. – haccks Nov 10 '15 at 07:42
  • @haccks I'd imagine they think it's simpler to explain, at least until they get to explaining how to pass a pointer by "reference." – IllusiveBrian Nov 10 '15 at 16:44
  • @Namfuak; May be the case, but this causes pain latter to undestand. Better to explain clearly from the beginning. – haccks Nov 10 '15 at 16:46
  • 1
    @Namfuak, explaining a term in a wrong way, missing out details, to make it simpler, sounds more dangerous to me then a complex explanation. – Haris Nov 10 '15 at 16:59
  • @Haris I agree, I don't think that it saves any time in the long run and will probably lead to weird questions in between where people try Googling "pass by reference C" and then get confused at the compiler errors attempting to use the C++ syntax they find. – IllusiveBrian Nov 10 '15 at 18:13
  • @Namfuak, Yes. And for people who have not read about C++, it is really hard to guess that there is something called `reference variable` that can be used. – Haris Nov 10 '15 at 18:16
  • 2
    @Insane I don't think it's misleading, it's just used in a different context - "reference" means something a bit different nowadays, with languages like C++ and C#. In more general terms, pointers *are* references to values. They just don't have other properties we associate with references nowadays. Since your teacher leads a course that's explicitly about C (and not C++), this is perfectly fine. You're basically complaining about using the term "computer" to refer to people who compute stuff - well, that's what it means! Sure, today you imagine a machine first, but that's just your context. – Luaan Nov 11 '15 at 13:40
  • 1
    @Namfuak You pass a pointer by reference by passing the pointer to the pointer. It's actually *simpler* - there's no second layer. The complications are a result of this simplicity - we just decided that it's a better idea to complicate some trivialities a bit so that we simplify other things later. And, well, the whole argument seems to be "This vaguely similar language uses a different terminology, which is confusing!" Well... so what? Languages do that all the time, both programming and natural. C++ and C# look very similar, and yet `struct` means something entirely different. So? – Luaan Nov 11 '15 at 13:43
  • If that makes you feel better, Java is even more confusing, because although everything is pass-by-value, pointers are officially called references. – biziclop Nov 11 '15 at 16:52
  • @biziclop, actually, after few hours of research and reading, i have come to a conclusion that it depends on the way you look at things. It can also be called *pass-by-reference*, and I am thinking of updating the answer. – Haris Nov 11 '15 at 16:56
  • @Hans I think it's much more clear cut. Imagine you pass a local variable by reference to a function that assigns a new value to the parameter. If the change is reflected back to the original local variable, it is pass-by-reference. If it doesn't, it isn't. In Java or C, if you re-assign the value of a parameter, nothing happens. – biziclop Nov 11 '15 at 17:07
  • @Haris so if passing a pointer is not pass by _reference_ (the very meaning of _pointer_), what is? – miraculixx Nov 11 '15 at 18:45
  • @miraculixx, Its not what you are passing, it is about how it is being passed.. But, (i have updated the answer), what you are saying is also not incorrect. – Haris Nov 12 '15 at 05:11
  • @Haris how do you pass by reference (if not passing the reference i.e. a pointer, instead of the value itself)? – miraculixx Nov 12 '15 at 15:48
  • @miraculixx, See the C++ example. – Haris Nov 12 '15 at 15:56
  • I must say, I am still confused. – rsonx Feb 10 '21 at 07:31
32

Reference is an overloaded term here; in general, a reference is simply a way to refer to something. A pointer refers to the object pointed to, and passing (by value) a pointer to an object is the standard way to pass by reference in C.

C++ introduced reference types as a better way to express references, and introduces an ambiguity into technical English, since we may now use the term "pass by reference" to refer to using reference types to pass an object by reference.

In a C++ context, the former use is, IMO, deprecated. However, I believe the former use is common in other contexts (e.g. pure C) where there is no ambiguity.

  • 4
    Clearly a pointer is a reference... Just not a c++ &reference... But it refers to some clump of memory – Grady Player Nov 10 '15 at 06:06
  • 1
    Indeed, I was once very confused knowing about x86 exceptions and trying to figure out while learning C++, why my `catch(...)` doesn't handle `#DE` exception (division by zero error). Turned out there's a similar overloading of terminology: C++ exceptions are completely unrelated to CPU exceptions. – Ruslan Nov 11 '15 at 09:12
  • In the C++ world, where *reference* means a specific language feature, I find it is best to use *handle* for the generic term -- it can be a reference, pointer, array index, map key, file descriptor, etc. And passing handles around may result in handle duplication, but the target object is shared. – Ben Voigt Nov 11 '15 at 15:12
17

Does C even have ``pass by reference''?

Not really.

Strictly speaking, C always uses pass by value. You can simulate pass by reference yourself, by defining functions which accept pointers and then using the & operator when calling, and the compiler will essentially simulate it for you when you pass an array to a function (by passing a pointer instead, see question 6.4 et al.).

Another way of looking at it is that if an parameter has type, say, int * then an integer is being passed by reference and a pointer to an integer is being passed by value.

Fundamentally, C has nothing truly equivalent to formal pass by reference or reference parameters.

To demonstrate that pointers are passed by value, let's consider an example of number swapping using pointers.

int main(void)
{
    int num1 = 5;
    int num2 = 10;

    int *pnum1 = &num1;
    int *pnum2 = &num2;
    int ptemp;

    printf("Before swap, *Pnum1 = %d and *pnum2 = %d\n", *pnum1, *pnum2);
    temp = pnum1;
    pnum1 = pnum2;
    pnum2 = ptemp;

    printf("After swap, *Pnum1 = %d and *pnum2 = %d\n", *pnum1, *pnum2);
}

Instead of swapping numbers pointers are swapped. Now make a function for the same

void swap(int *pnum1, int *pnum2)
{
     int *ptemp = pnum1;
     pnum1 = pnum2;
     pnum2 = temp;
}

int main(void)
{
    int num1 = 5;
    int num2 = 10;

    int *pnum1 = &num1;
    int *pnum2 = &num2;

    printf("Before swap, *pnum1 = %d and *pnum2 = %d\n", *pnum1, *pnum2);
    swap(pnum1, pnum2);

    printf("After swap, *pnum1 = %d and *pnum2 = %d\n", *pnum1, *pnum2);
}

Boom! No swapping!


Some tutorials mention pointer reference as call by reference which is misleading. See the this answer for the difference between passing by reference and passing by value.

Community
  • 1
  • 1
haccks
  • 104,019
  • 25
  • 176
  • 264
  • +1; While I still like @Haris' answer because it feels more complete, I hadn't seen this link even after Googling quite a bit! – Insane Nov 10 '15 at 07:51
  • "if an parameter has type, say, `int *` then an integer is being passed by reference and a pointer to an integer is being passed by value." -- I think that pretty much makes the crucial point. – CompuChip Nov 10 '15 at 13:02
  • 1
    @CompuChip, Integer is not being passed by reference, the address passed is being used to access the integer, since the address refers to the integer. – Haris Nov 11 '15 at 16:37
  • @Haris I wasn't talking about references in the C++ sense but in more general terms. To me, conceptually `int&` and `int*` are the same thing in this discussion. I just read the updates of 11 Nov to both the OP and your excellent answer and I think that distinction in terminology is the confusing thing here. Assuming that point of view has been discussed extensively in chat I won't pursue it further, but I feel like there is no fundamental misunderstanding here. – CompuChip Nov 12 '15 at 08:30
  • @CompuChip. Hmm, i agree. Once we go through and understand, it is evident that there is no right and wrong. – Haris Nov 12 '15 at 08:52
  • @CompuChip; *I think that pretty much makes the crucial point.*: Yes, it is. But it should be noted that in case of `int *` reference of object is pass by using pointer which is not the case with `int &`. – haccks Nov 12 '15 at 08:57
  • @haccks yes obviously there are differences such as the fact that an `int*` can be null, the fact that for `int*` you need different syntax and the fact that it is slightly easier to manipulate other memory than the passed variable through a pointer than it is through a reference. But I view those as superficial differences, the main point being that both `int*`and `int&` pass in the _identity_ of an integer, as opposed to just its _value_. Viewed alternatively, it passes in the _value_ of the pointer-to-int, not the identity itself (`f(int* p){p=0;}` does not change anything relevant). – CompuChip Nov 12 '15 at 09:21
  • @CompuChip; Yes. I mentioned this in the example in my answer. – haccks Nov 12 '15 at 09:23
  • 1
    @haccks so again, we all seem to agree :) – CompuChip Nov 12 '15 at 09:28
16

From the C99 standard (emphasis mine):

6.2.5 Types

20 Any number of derived types can be constructed from the object and function types, as follows:

...

— A pointer type may be derived from a function type or an object type, called the referenced type. A pointer type describes an object whose value provides a reference to an entity of the referenced type. A pointer type derived from the referenced type T is sometimes called ‘‘pointer to T’’. The construction of a pointer type from a referenced type is called ‘‘pointer type derivation’’. A pointer type is a complete object type.

Based on the above, what your professor said makes sense and is correct. A pointer is passed by value to functions. If the pointer points to a valid entity, its value provides a reference to an entity.

Community
  • 1
  • 1
R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • See the example that i have added, In that there is no explicit sending of address. That would be an example of proper pass-by-reference. If you are explicitly sending the address and it is received by a pointer, it is actually send by value only. – Haris Nov 10 '15 at 04:35
  • 8
    Well, yes, but we are back to the C, C++ apples and oranges again... e.g., there is no `void swap(float &x, float &y)` in C, only `void swap(float *x, float *y)` – David C. Rankin Nov 10 '15 at 05:43
  • 1
    @DavidC.Rankin Semantically they are the same. After execution the values of `x` and `y` are swapped. The syntax is different, but the meaning is exactly the same. – luk32 Nov 10 '15 at 11:55
11

"Passing by reference" is a concept. Yes, you are passing the value of a pointer to the function, but in that instance the value of that pointer is being used to reference the variable.

Someone else used a screwdriver analogy to explain that it is wrong to refer to the passing of pointers as passing by reference, saying that you can screw a screw with a coin but that that doesn't mean you would call the coin a screw driver. I would say that is a great analogy, but they come to the wrong conclusion. In fact, while you wouldn't claim a coin was a screwdriver, you would still say that you screwed the screw in with it. i.e. even though pointers are not the same as c++ references, what you are using them to do IS passing by reference.

tomd
  • 113
  • 7
6

C passes arguments by value, period. However, pointers are a mechanism that can be used for effectively passing arguments by reference. Just like a coin can be used effectively as a screw driver if you got the right kind of screw: some screws slit are even chosen to operate well with coins. They still don't turn the coins into actual screw drivers.

C++ still passes arguments by value. C++ references are quite more limited than pointers (though having more implicit conversions) and cannot become part of data structures, and their use looks a lot more like the usual call-by-reference code would look, but their semantics, while very much catered to match the needs of call-by-reference parameters, are still more tangible than that of pure call-by-reference implementations like Fortran parameters or Pascal var parameters and you can use references perfectly well outside of function call contexts.

5

Your professor is right. By value , it is copied. By reference, it is not copied, the reference says where it is.

By value , you pass an int to a function , it is copied , changes to the copy does not affect the original.

By reference , pass same int as pointer , it is not copied , you are modifying the original.

By reference , an array is always by reference , you could have one billion items in your array , it is faster to just say where it is , you are modifying the original.

BobRun
  • 756
  • 5
  • 12
3

In languages which support pass-by-reference, there exists a means by which a function can be given something that can be used to identify a variable know to the caller until the called function returns, but which can only be stored in places that won't exist after that. Consequently, the caller can know that anything that will be done with a variable as a result of passing some function a reference to it will have been done by the time the function returns.

Compare the C and C# programs:

// C               // C#
int x=0;           int x=0;
foo(&x);           foo(ref x);
x++;               x++;
bar();             bar();
x++;               x++;
boz(x);            boz(x);

The C compiler has no way of knowing whether "bar" might change x, because foo() received an unrestricted pointer to it. By contrast, the C# compiler knows that bar() can't possibly change x, since foo() only receives a temporary reference (called a "byref" in .NET terminology) to it and there is no way for any copy of that byref to survive past the point where foo() returns.

Passing pointers to things allows code to do the same things that can be done with pass-by-ref semantics, but pass-by-ref semantics make it possible for code to offer stronger guarantees about things it won't do.

supercat
  • 77,689
  • 9
  • 166
  • 211