3

I know that there is no Call by reference in C language. but, Some people say that there is a Call by reference in C. I'm confused.

As far as I know, when handing over the factor to the function in C, I know that the value transferred to the function is received by making a local copy as a parameter.

However, in C++, "Call by reference" is possible because "the same element that differs only from the factor and name" is created by the reference "&". Is that true?

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
GT K
  • 51
  • 4
  • 6
    "Some people say that there is a Call by reference in C." Who says that? Can you cite some sources so we can see exactly what they're saying? – John Kugelman Sep 19 '22 at 02:49
  • When you search for call by reference and value on the Internet, it is divided into two values. C includes or does not include a reference.. https://www.tutorialspoint.com/cprogramming/c_function_call_by_reference.htm However, I learned that reference means type& while learning c++. – GT K Sep 19 '22 at 02:55
  • The `type&` notation is exclusively C++; there is nothing analogous in C. You have to pass a pointer (or a pointer to a pointer, or …) to a function to get (more or less) the effect of passing by reference in C, but you have to use the appropriate pointer dereferencing notation in the called function (whereas in C++ with explicit references, you don't have to change the notation). – Jonathan Leffler Sep 19 '22 at 03:07
  • You can look at assembly code if you want to know how c++ implements pass parameter by reference. – Frank Sep 19 '22 at 03:26
  • 3
    don't use shitty things like tutorialspoint. Read [a good C book](https://stackoverflow.com/q/562303/995714) instead – phuclv Sep 19 '22 at 03:54
  • 2
    I'm with phuclv. **Books > Tutorials** every single time. Get a book you *trust* and keep it within arm's reach whenever you're working on C. I had the K&R C book on my desk for years before I'd internalized it all. – tadman Sep 19 '22 at 05:10
  • 3
    Various C++ programmers have this crazy idea that there is no pass by reference in C just because C++ invented something they decided to call references. But the term "pass by reference" is much older than C++ and much broader and generic. It simply means pass by address instead of making a hard copy. The same people who say there are no references in C speaks of unary `*` as _dereferencing_ in the next breath... "no references" is some muddy C++ sub-culture thing. – Lundin Sep 19 '22 at 06:37
  • Closely related: *[What's the difference between passing by reference vs. passing by value?](https://stackoverflow.com/q/373419/2402272)* – John Bollinger Sep 19 '22 at 15:13
  • 1
    It's interesting that the apparent controversy here is is not observed in the Java community, despite Java language semantics being very closely analogous to C's in this area: in Java, all arguments are (undisputedly) passed by value, including arguments of reference type. No arguments are passed by reference; references are passed by value. I'd even say that that's a good characterization of C++, but the C++ community seems to view the matter differently in general. – John Bollinger Sep 19 '22 at 15:24
  • 1
    As for C, the language specification says "In preparing for the call to a function, the arguments are evaluated, and **each parameter is assigned *the value* of the corresponding argument**" (C17 6.5.2.2/4; emphasis added). That's pass by value. The spec also notes some implications: "A function may change the values of its parameters, but these changes cannot affect the values of the arguments. On the other hand, it is possible to pass a pointer to an object, and the function may change the value of the object pointed to" (C17 footnote 95). – John Bollinger Sep 19 '22 at 15:32
  • It's all pass-by-value in C, but ... if you pass the address of an object, then the function receives a pointer to the object holding the original address -- which can be modified in the function and the change survives the function return. While you are simply passing the address by-value, this is what is commonly referred to as passing by reference in C. If you just pass an object by-value, then the function receives a copy-of the object (as if locally declared in the function) and any changes made in the function will be lost on return. – David C. Rankin Sep 19 '22 at 21:37

7 Answers7

9

I know that there is no Call by reference in C language.

Correct. C always passes by value.

Some people say that there is a Call by reference in C. I'm confused.

They are wrong. This is very easy to test.

Let's start by looking at this small Perl program.

use 5.014;

sub f {
   $_[0] = 456;   # $_[0] is the first argument.
}

my $x = 123;
f( $x );
say $x;   # 456

Changing the parameter changed the argument. This is an example of pass by reference. Perl arguments are passed by reference.

Now let's do the same thing in C.

#include <stdio.h>

void f( int x ) {
   x = 456;
}

int main( void ) {
   int x = 123;
   f( x );
   printf( "%d\n", x );   // 123
}

Changing the parameter had no effect on the argument. This is an example of pass by value. C's arguments are passed by value.

You can use pointers to achieve a similar result.

#include <stdio.h>

void f( int *xp ) {
   *xp = 456;
}

int main( void ) {
   int x = 123;
   f( &x );
   printf( "%d\n", x );   // 456
}

Note that the argument (the pointer) is still passed by value. Changing xp itself (as opposed to *xp) has no effect on the caller.

Same goes for arrays. The degenerate into a pointer which is passed by value.

#include <stdio.h>

void f( char a[] ) {
   a = "def";
}

int main( void ) {
   char a[] = "abc";
   f( a );
   printf( "%s\n", a );   // abc
}

This could be called passing a reference. It is not passing by reference, however.


However, in C++, "Call by reference" is possible

Correct.

C++ normally uses pass by value.

#include <iostream>

using namespace std;

void f( int x ) {
   x = 456;
}

int main( void ) {
   int x = 123;
   f( x );
   cout << x << endl;   // 123
}

But pass by reference can be requested using &.

#include <iostream>

using namespace std;

void f( int &x ) {
   x = 456;
}

int main( void ) {
   int x = 123;
   f( x );
   cout << x << endl;   // 456
}
ikegami
  • 367,544
  • 15
  • 269
  • 518
  • Comments are not for extended discussion; this conversation has been [moved to chat](https://chat.stackoverflow.com/rooms/248282/discussion-on-answer-by-ikegami-is-c-language-call-by-reference). – Samuel Liew Sep 23 '22 at 02:37
5

I know that there is no Call by reference in C language. but, Some people say that there is a Call by reference in C. I'm confused.

Your confusion is, I'm afraid, inevitable, but it's not your fault.

People have been arguing about this question for a long time. (There's an FAQ list entry on the question that dates to the 1990's.) I didn't realize it was still a matter of debate, but evidently it is, because the same confusion you've experienced has been repeated (which is to say, validated) in the answers posted right here on this Stack Overflow question, where you hoped you'd get a definitive answer.

Depending on how you define your terms, all of the following statements are more or less true:

  • C does not have pass by reference. C always passes arguments by value.
  • C lets you simulate pass by reference, by passing a pointer instead. But the pointer is passed by value.
  • Arrays in C are passed by reference, because the array reference in the function call decays into a pointer to the array's first element. (But the pointer is passed by value.)
  • C++ has reference parameters, meaning that the programmer doesn't have to explicitly use the & operator in the call, or the * operator in the function. (But the implementation of that reference involves something very much like a pointer which is, again, passed by value.)

Or, in other words, for a sufficiently formal and restrictive definition of the term "pass by reference", C does not have it. But it has a couple of things that are pretty close, perhaps close enough to satisfy a less-formal definition, or to let you say, "You can get something a lot like call-by-reference in C, if you want."

Steve Summit
  • 45,437
  • 7
  • 70
  • 103
  • 1
    C++ passes references by value, so by using the same flawed arguments, then C++ doesn't have pass by reference either. `void pointer (const std::string* str)` and `void ref (const std::string& str)` yields _exactly the same machine code_. I guess you could _simulate_ pass by reference in C++, but it passes references by value... https://godbolt.org/z/3WsW3sPPr – Lundin Sep 20 '22 at 06:18
  • 1
    What this debate really boils down to is C++ programmers trying to explain the existence of references as if they are somehow supernatural and magical, impossible to achieve for other languages. But the true purpose of them all along is really just to provide syntactic sugar over pointer dereferencing and the somewhat awkward `->` syntax of C, while at the same time handling const correctness of the pointer itself. It's really just the very same thing as the `arr[i ]` operator being more readable than `*(arr+i)`. – Lundin Sep 20 '22 at 06:24
  • The C++ side discussion has some value, but detracts from focusing on this answer's good points. – chux - Reinstate Monica Sep 21 '22 at 15:30
4

C sometimes appears to pass by reference. The detail is that the argument goes through automatic conversions and that argument is passed by value. The effect is that the original argument experiences a pass-by-reference.


  • When an argument is a function, it may look/act like it is pass by reference. Functions are converted to the address of a function. The function sqrt is not passed by value. foo() receives the address of the function as a function pointer.

foo(sqrt);


  • An array looks like it is passed by reference in that bar() does not receive the value of the array. What happened under the table is that the array is converted to the type and address of the first element and bar() receives a pointer to a char. bar() may do things that change s[], exactly what pass by refence does in other languages, yet in C there is a technical under-the-table conversion that maintains the idea of pass only by value.

char s[1];
bar(s);

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • 2
    yeah. That's why I was confused. – GT K Sep 19 '22 at 03:41
  • 1
    @GT K, IOWs, from the original argument stand-point, C has limited pass-by-reference. Yet the real arguments passed are passed by value. – chux - Reinstate Monica Sep 19 '22 at 03:44
  • 2
    It might be worth explaining the array argument syntax, that `int arg[10]` is literally same as `int *arg`, including `sizeof`. – hyde Sep 19 '22 at 04:50
  • @hyde Please expand more of your idea and how it applies here. – chux - Reinstate Monica Sep 19 '22 at 10:08
  • I mean, that *"does not receive the value of the array"* may be misunderstood. The function does not receive an array at all. It may look like an array if you use the array syntax, but it is not an array in any sense. It's just a pointer, and makes no distinction about where the object pointed to is (array, variable, parameter, struct field, char buffer....). – hyde Sep 21 '22 at 15:12
  • @hyde Consider another _under the table_ type change where the value remains the same. `short i = ...; abs(i);`, `abs()` receives the same value of the `short`, but as an `int`. `bar(s)` does not receive the value of array `s`, but a different value and type. The 2nd point emphasizes that value change. – chux - Reinstate Monica Sep 21 '22 at 15:28
  • What I mean is *"exactly what pass by refence does in other languages"* is not quite right. In other languages, which use pass by reference, the size of the array would be available. In C it is not. It's not just "a different mechanism for same thing", it's a subtly different thing. Why this matters is, a lot of novice programmers make the mistake of thinking that "ok, if I use array syntax in function parameter, the array is passed by refeernce", and then they use `sizeof`, which does not work because it is not an array passed by reference. – hyde Sep 21 '22 at 15:35
  • @hyde Consider separating _pass by refence_ into the caller's and receiver's points of view. From the caller's point-of-view `bar(s)` is a _pass by reference_ (the main gist of this answer). "size of the array would be available" is about the receiving side POV - more along the lines of _receive by reference_ and remains with limitations you express. – chux - Reinstate Monica Sep 21 '22 at 15:56
  • Well, it's quite common to be required to pass the array size as a separate argument. So the conversion to plain pointer also leaks to caller side sometimes, often, perhaps even most of the time. The caller needs to do things they wouldn't need to do if it was a real reference (by which I mean, something which includes full type information). – hyde Sep 21 '22 at 16:02
  • ...and the reason why I mentioned this is, _I_ think this is important enough nitty gritty detail, that it bears being explicit about it in an answer like this. But it's your answer, I'm not going to down-vote it over this :-) – hyde Sep 21 '22 at 16:05
3

I know that there is no Call by reference in C language. but, Some people say that there is a Call by reference in C. I'm confused.

The traditional definition of "pass by reference" is an aspect of subprogram calling semantics providing that the subprogram's parameters are bound to the same objects that are designated by the caller as the corresponding subprogram arguments.1,2 This has the effect that if the subprogram modifies the object identified by one of its parameters, including by assignment, then the caller can observe that modification (provided that the caller retains a way to examine that object). This is the typical implementation of Fortran's call semantics, among others.

For example, consider a program of this form (expressed in a polyglot pseudocode):

subprogram sub1(x)
x = 0
end

integer a
a = 42
call sub1(a)
print(a)

In a language with pass-by-reference semantics, the assignment to x in sub1 will modify the value of a in the caller, with the result that the program prints "0".

Pass-by-value is the main alternative: the names of subprogram parameters are not bound to the objects specified by the caller. They are instead bound to different objects with (initially) the same values as those presented by the caller. In a language with pass-by-value semantics, a program such as the above would be expected to print "42", as the subprogram's parameter x refers to a different object than the caller's a, therefore the subprogram's assignment to x is not visible to the caller.

As far as I know, when handing over the factor to the function in C, I know that the value transferred to the function is received by making a local copy as a parameter.

Yes, this is mandated by the C language specification:

An argument may be an expression of any complete object type. In preparing for the call to a function, the arguments are evaluated, and each parameter is assigned the value of the corresponding argument.

(C17 6.5.2.2/4; emphasis added)

As judged via the definitions above, this is unequivocally pass-by-value in all cases. However, there are a couple of cases that require special attention in this context:

  1. One can pass the address of an object to a function -- for example, by means of the unary & operator. In that case, the function can modify the pointed-to object via the pointer it receives. Some people are inclined to characterize this as pass-by-reference, but it does not satisfy the definition above, because the argument was never the pointed-to object in the first place. Moreover, assignment to the received pointer itself does not modify the argument presented by the caller or the object to which it points.

  2. The arguments presented by the caller are the results of evaluating the expressions presented, and C has some cases where the effect of that may be surprising to the uninitiated, especially

    • functions. Wherever the name of a function appears in a valid expression that is evaluated, it is automatically converted to a pointer.3 In particular, when the name of a function appears in the argument list of a function call, the corresponding parameter receives a pointer to the function. The called function can use that pointer to call the function it points to, even if that function's identifier is not in scope. But the function has not been passed by reference (by the above definition), for if the called function assigns a new value to the parameter, that does not modify the function it originally pointed to (nor the caller's copy of the function pointer, if it retains one).

    • arrays. C specifies that with only a few, narrow exceptions, expressions of array type are automatically converted to pointers. I think it's fair and consistent to describe that as the result of evaluating a (sub)expression of array type being a pointer to the first element of the array. The argument lists to function calls are no exception, so when you specify an array as a function argument, the corresponding function parameter receives a pointer to the first array element.

      As a result, the called function can modify the array's elements via the pointer it receives. Some people describe that effect as the array having been passed by reference, but it doesn't actually satisfy the above definition. The parameter doesn't even have the same type as the caller's array, and moreover, if you assign a new value to the parameter itself then the effect is visible only in the function. In this sense, modifying array elements via a pointer received as a parameter is analogous to calling a function via a function pointer received as a parameter.


However, in C++, "Call by reference" is possible because "the same element that differs only from the factor and name" is created by the reference "&". Is that true?

Yes, one of the things that C++ has that C does not is references, and one of the major uses of references is providing pass-by-reference semantics that satisfy the above definition. It's not quite pass-by-reference in the Fortran sense because the parameter has a different type than the corresponding argument, but for most purposes, the parameter can be used in the same ways, and with the same effects, as the argument to which it is bound. In particular, assignment to a reference does affect the referenced object.

C++ references have some additional properties that differentiate them from pointers, among them:

  • A reference can be created only from another, valid object, either as a reference to that object or, if that object is itself a reference, as a copy of that reference (referring to the same object).

  • References cannot be rebound to different objects.

These play well with using C++ references for pass-by-reference.


Until now I have grounded my discussion in the definition given above, but it will be clear from the answers and comments given that there is a controversy here over whether that remains an appropriate definition. Some claim that the language has moved on, and in particular that in the context of C, the term "pass by reference" has become accepted as including passing a pointer. To be sure, some do use the term that way. On the other hand, "accepted" is clearly too strong a term, because plenty of others, including some voicing their opinions here, insist that it is is imprecise, sloppy, or simply wrong to describe passing a pointer to an object as passing that object by reference.

One thing to consider here is that the conventional meaning of these terms in context of most programming languages other than C has not appreciably moved from the traditional ones, even for much younger languages. C++ in particular is relevant because of the shared history and strong interoperability of these, and no C++ programmer would characterize passing a pointer as pass by reference. But the terminology is also well established in Java, which has only pass by value, including passing references by value, but not pass by reference. It also comes up in Python, which is like Java but more so, because all argument passing there is passing references by value. The distinction is important for explaining the semantics of those languages, as indeed it is for C, too.

Therefore, at present, if

  • you are engaging in comparative analysis of computer languages,
  • you want to express your ideas with maximum precision, or
  • you want to avoid, in many cases, earning a point of disrespect from a portion of your audience

then you will avoid conflating passing pointers with pass by reference. But if you do conflate the two then you can reasonably expect to be understood, at least in C-specific context.


1 Wikipedia definition
2 Strongly supported Stack Overflow definition
3 Including in their most common context, function calls: "The expression that denotes the called function shall have type pointer to function" (C17 6.5.2.2/1).

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
2

But, Some people say that there is a Call by reference in C. I'm confused.

This depends on how you define the term "call by reference":

Three years ago, I worked for a company in the automotive industry:

Pointer arguments that were pointing to a (single) variable (and not to an array) of the type someType were neither defined as "arguments of the type someType *" nor as "pointers to a someType" but as "'call by reference' arguments of the type someType".

You could also see this at the "[out]" or "[inout]" tag in the comments:

/*! \brief Example function (non-AUTOSAR)
 *  \param[in]    foo    Value of the "foo" force
 *  \param[out]   bar    Value of the "bar" speed
 *  \param[inout] foobar Current value of the "foobar" state
 *  \return  True if calculating "bar" succeeded */
bool someFunction(someType foo, someType * bar, someType * foobar)
{
    ...
}

Microsoft's documentation of the Windows API seems to see this in a similar way - for example here:

BOOL GetExitCodeProcess(
   [in]  HANDLE  hProcess,
   [out] LPDWORD lpExitCode
);
Martin Rosenau
  • 17,897
  • 3
  • 19
  • 38
  • In fact passing a pointer to a variable is *functionaly* equivalent of passing that variable by reference. And under the hood, languages that pass by reference do pass a low level pointer. That is the reason why some people say that you can pass variable by reference in C language by actually passing pointers to those variables. – Serge Ballesta Sep 19 '22 at 07:15
  • Re "*This depends on how you define the term "call by reference"*", The term is [well-defined](https://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_reference). – ikegami Sep 19 '22 at 13:56
  • @ikegami Unfortunately, it's not that simple: According to the definition found in Wikipedia, a `ref` argument in C# is neither "call-by-reference" (because in C#, reference arguments are not passed **implicitly** but **explicitly**) nor "call-by-value" (because a reference is passed and not a value)... – Martin Rosenau Sep 19 '22 at 14:07
  • 1) I'm not sure why you think it would be relevant if C# didn't provide pass-by-reference. 2) But C# does support pass-by-reference. It's even mentioned in the article. The fact that you have to use `out` (or `&` in C++) to indicate you want pass-by-reference doesn't change that. – ikegami Sep 19 '22 at 14:13
  • @ikegami I was focusing on the **function call**, not on what you do inside the function: In C#, you have to use an additional keyword in the function call: `foo(ref bar)`. So it is not "implicit" - and you may do the same in C: `foo(&bar)`. However, if you are focusing what you do **inside the function**, you are right: In C, you need an additional operator (`*bar=5`) while you don't need that in C# (`bar=5`). – Martin Rosenau Sep 19 '22 at 14:25
  • 1
    Re "*So it is not "implicit"*", So? nothing says you don't have to declare that you are using pass by ref explicitly. – ikegami Sep 19 '22 at 14:30
  • @ikegami One other thing: "*The term is well-defined*": There are very few terms whose meaning is either defined by a law (German law for example defines "lawyer", "architect", "psychologist" or "medical doctor") or > 90% of all "users" agree with a certain definition. For all other terms the meaning may vary: In the automotive software industry, the exact definition of "call-by-reference" may differ from the definition in computer science. – Martin Rosenau Sep 19 '22 at 14:34
2

“Pass by reference”1 is an old computer programming phrase that antedates the “reference” feature built into C++. It means providing a pointer to an object. The C standard says a pointer “provides a reference” (C 2018 6.2.5 20). References can be provided either manually by a programmer writing some explicit notation or by a feature built into a programming language.

When C++ developers named a new feature a “reference,” that did not change the prior usage of the term. When discussing “passing by reference” in languages other than C++ or others that provide built-in references, the phrase has its classic meaning.

C supports passing by reference (manually) but does not provide it as a built-in feature, except to the extent that arrays and functions undergo automatic conversions and adjustments that effect passing by reference. Programmers understand from context that “pass by reference” refers to passing a pointer in C and passing a built-in reference type in C++.

Footnote

1 The question uses the phrase “call by reference,” but this is an imprecise use of terminology. Whether we are discussing C++ or C, the issue is how arguments are passed, not how functions are called.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • @ikegami: You seem to have entered a comment on the wrong answer. My answer does not contain the phrase you quote; that is in another answer. – Eric Postpischil Sep 19 '22 at 14:02
  • The term is [well-defined](https://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_reference). The fact that it's old doesn't change its meaning. You could argue there are better things to talk about, but you can't simply pretend the term means something else. /// Re "*The C standard says a pointer “provides a reference”*", Indeed, but that doesn't mean you pass by reference. You can pass *a* reference without passing *by* reference. The reference, of course, is passed by value. – ikegami Sep 19 '22 at 14:05
  • 1
    (Sorry, there was extra at the front.) – ikegami Sep 19 '22 at 14:05
  • 1
    @ikegami: My answer does not say “call by reference” is not well-defined. It says it is imprecise. That does not mean it is wrong or even inaccurate. It simply means it lacks precision, allowing some ambiguity about what is meant. As for whether we can “call by reference” or “pass by reference,” we can indeed pass a reference to an object in C, and the phrase “pass by reference” refers to that. When person is talking about some C code and says some `x` is passed by reference, they mean a pointer to `x` is passed. – Eric Postpischil Sep 19 '22 at 14:27
  • 1
    You're passing a reference, but the referenced is passed by value. We have received countless questions where people expect changes to the pointer to be mirrored in the caller. But it isn't. – ikegami Sep 19 '22 at 14:35
  • 1
    @ikegami: Re “You're passing a reference, but the referenced is passed by value”: Yes. Nonetheless, people speak of this as passing by reference. Re “We have received countless questions where people expect changes to the pointer to be mirrored in the caller”: Yes, and they should be taught otherwise. There is no conflict between teaching them that C passes arguments by value and people using the phrase “pass by reference” in C mean passing a pointer. – Eric Postpischil Sep 19 '22 at 14:40
  • 1
    [The prevailing Stack Overflow defintiion of "pass by reference"](https://stackoverflow.com/a/430958/2402272) disagrees with this answer's very loose definition of the term, and hence with the novel idea that it is possible to pass by reference *manually* where the language in use does not provide pass by reference as part of its semantics. – John Bollinger Sep 19 '22 at 15:11
  • @JohnBollinger: Even if we were voting, that would not change how people use the language. For now, at least, people who are talking about C code and say some `x` is passed by reference, they mean a pointer to `x` is passed. You might not like that, you might think lots of people want the term to mean something else, you might prescribe something else, but it is nonetheless what people mean when they are talking about C code. – Eric Postpischil Sep 19 '22 at 16:42
  • 1
    Indeed not, @EricPostpischil, but the definition I linked and [the Wikipedia one](https://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_reference) that says substantially the same thing provide a good guide for how people do use the language. And even if I accepted the language to have shifted such that it was correct to refer to passing a pointer to an object as passing that object "by reference", the definition you present is far looser than any I've ever heard. It is *not*, in its full generality, what people mean by the term "pass by reference". – John Bollinger Sep 19 '22 at 17:25
  • @JohnBollinger: The Wikipedia page cites no reference for its “call by reference” section other than a diatribe expressing personal opinion with no attempt to reflect actual use. I am not interested in the “full generality” of what people mean by “pass by reference”; I am writing about what it means in the context of C. Different people use terms differently in different contexts. Do you contend that a person who, in speaking of a C program, says `x` is passed by reference means something other than passing a pointer to `x`? – Eric Postpischil Sep 19 '22 at 17:30
  • 1
    @EricPostpischil, it is not specifically a C-language concept, so "what it means in the context of C" is how the general concept applies to C. You cannot divorce that from the general concept itself. Some people do refer to passing pointers as passing the pointed to object by reference, but there are many who do not accept that usage to be correct. But again, even setting that aside, the definition presented in this answer is far broader than that, or than any I've ever heard anyone else propose or use. – John Bollinger Sep 19 '22 at 17:40
  • @JohnBollinger: People use language the way they use language; they do not obey your rules about applying some general concept as if there were a central authority governing their speech. They can and do use it the way they want even if you say they must behave otherwise. – Eric Postpischil Sep 19 '22 at 17:43
  • Yes, @Eric, but *nobody* uses the definition you have presented. – John Bollinger Sep 19 '22 at 17:44
  • @JohnBollinger: Which specific thing are you complaining about? The sentence “It means providing a means of accessing some value stored in memory”? Or something else? Would you it make you happy if that were narrowed to just a pointer? – Eric Postpischil Sep 19 '22 at 17:46
  • Yes, that sentence is the definition of "pass by reference" asserted by this answer, which in fact nobody uses. If it were narrowed to just passing a pointer the object then I would accept that that it reflected some people's usage. – John Bollinger Sep 19 '22 at 17:50
  • @JohnBollinger: Updated. – Eric Postpischil Sep 19 '22 at 17:55
2

In C, all function arguments are passed by value, meaning each argument expression in the function call is fully evaluated and the result of that evaluation is passed to the function:

#include <stdio.h>

void swap( int a, int b )
{
  int tmp = a;
  a = b;
  b = tmp;
}

int main( void )
{
  int x = 10, y = 10;
  printf( "Before swap: x = %d, y = %d\n" );
  swap( x, y );
  printf( " After swap: x = %d, y = %d\n" );

  return 0;
}

The formal parameters a and b in the definition of swap are different objects in memory from the actual parameters x and y in main. The expressions x and y are fully evaluated, and the results of those evaluations (the values 10 and 20) are copied to a and b. Changing the values of a and b has no effect on x or y, and the output of the program will be

Before swap: x = 10, y = 20
 After swap: x = 10, y = 20

We can fake pass-by-reference semantics by passing pointer values:

#include <stdio.h>

void swap( int *a, int *b )
{
  int tmp = *a;
  *a = *b;
  *b = tmp;
}

int main( void )
{
  int x = 10, y = 10;
  printf( "Before swap: x = %d, y = %d\n" );
  swap( &x, &y );
  printf( " After swap: x = %d, y = %d\n" );

  return 0;
}

Instead of passing the values of x and y, we're passing the results of the expressions &x and &y, which evaluate to the addresses of x and y.

a and b are still separate objects in memory from x and y, but instead of receiving the values of x (10) and y (20), they receive the addresses of x and y.

The expressions *a and *b can kinda-sorta be thought of as aliases for x and y, such that writing a new value to *a is the same as writing a new value to x and writing a new value to *b is the same as writing a new value to y. But this is not true pass-by-reference - it's passing pointers by value and manually dereferencing the pointers. The output of this program will be

Before swap: x = 10, y = 20
 After swap: x = 20, y = 10

Switching to C++:

#include <iostream>

void swap( int &a, int &b )
{
  int tmp = a;
  a = b;
  b = tmp;
}

int main( void )
{
  int x = 10, y = 20;
  std::cout << "Before swap: x = " << x << ", y = " << y << std::endl;
  swap( x, y );
  std::cout << " After swap: x = " << x << ", y = " << y << std::endl;
  return 0;
}

The parameter declarations int &a and int &b declare a and b as references - a and b are not separate objects in memory, but rather they are alternate names or aliases for the objects designated by x and y1. You do not need to explicitly dereference a or b in the C++ code the way you have to in the C code. Like the second C example, the output will be:

Before swap: x = 10, y = 20
 After swap: x = 20, y = 10

  1. Logically speaking, anyway - the compiler may be using pointers under the hood to accomplish this, but that's hidden from you. As far as the behavior of the code is concerned, a and b are not independent objects from x and y.
John Bode
  • 119,563
  • 19
  • 122
  • 198