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:
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.
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).