views:

1070

answers:

11

If C does not support passing a variable by reference, why does this work?

#include <stdio.h>

void f(int *j) {
  (*j)++;
}

int main() {
  int i = 20;
  int *p = &i;
  f(p);
  printf("i = %d\n", i);

  return 0;
}

Output

$ gcc -std=c99 test.c
$ a.exe
i = 21 
+15  A: 

In C, Pass-by-reference is simulated by passing the address of a variable (a pointer) and dereferencing that address within the function to read or write the actual variable. This will be referred to as "C style pass-by-reference."

Source: www-cs-students.stanford.edu

0A0D
+8  A: 

Your example works because you are passing the address of your variable to a function that manipulates its value with the dereference operator.

While C does not support reference data types, you can still simulate passing-by-reference by explicitly passing pointer values, as in your example.

The C++ reference data type is less powerful but considered safer than the pointer type inherited from C. This would be your example, adapted to use C++ references:

void f(int &j) {
  j++;
}

int main() {
  int i = 20;
  f(i);
  printf("i = %d\n", i);

  return 0;
}
Daniel Vassallo
That Wikipedia article is about C++, not C. References existed before C++ and don't depend on special C++ syntax to exist.
Roger Pate
@Roger: Good point... I removed explicit reference to C++ from my answer.
Daniel Vassallo
@Daniel: And that new article says "a reference is often called a pointer" which isn't quite what your answer says.
Roger Pate
+12  A: 

Because there is no pass-by-reference in the above code. Using pointers (such as void func(int* p)) is pass-by-address. This is pass-by-reference in C++ (won't work in C):

void func(int& ref) {ref = 4;}

...
int a;
func(a);
// a is 4 now
Alexander Gessler
+1  A: 

'Pass by reference' (by using pointers) has been in C from the beginning. Why do you think it's not?

Maurits Rijk
Because it's technically not passing by reference.
Mehrdad Afshari
Passing a pointer value is not the same as pass-by-reference. Updating the value of `j` (*not* `*j`) in `f()` has no effect on `i` in `main()`.
John Bode
+1 to John Bode's comment.
Jim In Texas
It *is semantically the same thing* as passing by reference, and that's good enough to say it is passing by reference. True, the C Standard does not use the term "reference", but that neither surprises me nor is a problem. We are also not speaking standardese on SO, even though we may refer to the standard, otherwise we'd see no one talking about rvalues (the C Standard doesn't use the term).
Roger Pate
@Jim: Thanks for telling us it was you that upvoted John's comment.
Roger Pate
+42  A: 

Because you're passing the value of the pointer to the method and then dereferencing it to get the integer that is pointed to.

tvanfosson
+1 for mentioning the phrase **passing the value**. That's the key point.
Mehrdad Afshari
+1  A: 

Because you're passing a pointer(memory address) to the variable p into the function f. In other words you are passing a pointer not a reference.

dave
+6  A: 

You're passing a pointer(address location) by value.

It's like saying "here's the place with the data I want you to update."

antony.trupe
+3  A: 

You're not passing an int by reference, you're passing a pointer-to-an-int by value. Different syntax, same meaning.

xan
+1 "Different syntax, same meaning." .. So the same thing, as the meaning matters more than the syntax.
Roger Pate
+1  A: 

In C, to pass by reference you use the address-of operator & which should be used against a variable, but in your case, since you have used the pointer variable p, you do not need to prefix it with the address-of operator. It would have been true if you used &i as the parameter: f(&i).

You can also add this, to dereference p and see how that value matches i:

printf("p=%d \n",*p);
tommieb75
Why did you feel the need to repeat all of the code (including that comment block..) to tell him he should add a printf?
Roger Pate
Roger Pate
+2  A: 

p is a pointer variable. Its value is the address of i. When you call f, you pass the value of p, which is the address of i.

Anssi
+1  A: 

No pass-by-reference in C, but p "refers" to i, and you pass p by value.

Pavel Radzivilovsky