views:

1348

answers:

9

I have been studying Java for a few months and am now starting to learn C.

I am a little confused, I was under the impression that passing an object by reference and passing a pointer to that object were the same thing: I thought the difference was that in Java all passing of objects is done with pointers automatically, where as in C one has to actually sprinkle little asterisks and ampersands here and there. Recently, in conversation, I was assured that there was a difference!

What is the difference between passing by reference and passing a pointer?

+3  A: 

The differences are subtle. At an assembly level, in both cases the address of the object is passed to the function. However, in the pointer case the parameter is an independent pointer which can be used to modify the target object (*pch = 'x') or can be used to access a different object (pch = "newstr"). In the reference case, the parameter is automatically indirected to the target object.

Denis Hennessy
+1  A: 

If you are studying C (rather than C++), then there are no references.

The term "pass by reference" in C simply means that you are passing a pointer as the address in which the value will be stored, so that the function can change its value. Otherwise, you're passing by value which means that a copy of the variable is generated on the stack and modifications have no impact.

In many ways this is similar to what you see in Java, except that in Java you don't have to explicitly turn things into a pointer or dereference them. In other words, when you pass a pointer, the address is copied on the stack, so if your function changes the pointer (rather than the data it points to), the changes disappear when you are done with the function. Similarly, when you pass an object reference in Java, you can change the contents of the object (e.g., by calling functions), but changing the varialbe to point at anothr object will have no effect once you leave.

If you were using C++ (which looks like C), then you can pass by reference, in which case you don't need to deal with pointers, and changes to the variable in the function actually change the external value directly (except that you can't make it point at something else).

Uri
Hey, could it be said that: "pointer" is a data type, and "reference" is just a way* to deal with data? One is a thing, the other is a technique?* I'm trying to avoid the ambiguity of using "method" here
Ziggy
A pointer is a data type for sure. However, in C++ (which most C people eventually use) there is a data type called a reference. This is a problem because in C++ there are actually two ways of "passing by reference", via actual references and via pointers. So "pass by reference" is a way.
Uri
+1  A: 

A few things

  • C has no references (in spite of C++)
  • Java has no pointers
  • The difference between pointers and references is, that pointers are practically memory addresses you can calculate with. References can not be calculated with
  • Java and C pass by value (When passing an object in Java, the reference is copied to the function)
Johannes Weiß
I suggest you remove the word "by default" from the last bullet - C and Java pass by value, end of story.
Jon Skeet
+2  A: 

I believe a pointer is a variable that contains a reference. With & you can obtain a memory direction ( reference ), and with * you can access to the content of a memory direction. I suggest the book The C programming Language .

Regards

Matias
+2  A: 

True pass-by-reference means that you can assign a new value to the reference, and this new value will be visible in the calling context just like inside called method.

In Java, this is not possible, because object references are passed by value.

Michael Borgwardt
+1  A: 

There's a recent article by Eric Lippert about this. He's a programmer on the C# compiler, but whatever he says there has enough generality to be extended to other GC languages such as Java:

http://blogs.msdn.com/ericlippert/archive/2009/02/17/references-are-not-addresses.aspx

Quote from the article:

Pointers are strictly "more powerful" than references; anything you can do with references you can do with pointers. [...]

Pointers are typically implemented as addresses. An address is a number which is an offset into the "array of bytes" that is the entire virtual address space of the process. [...]

For all these reasons we do not describe references as addresses in the specification. The spec just says that a variable of reference type "stores a reference" to an object, and leaves it completely vague as to how that might be implemented. Similarly, a pointer variable stores "the address" of an object, which again, is left pretty vague. Nowhere do we say that references are the same as addresses.

So, in C# a reference is some vague thing that lets you reference an object. You cannot do anything with a reference except dereference it, and compare it with another reference for equality. And in C# a pointer is identified as an address.

By contrast with a reference, you can do much more with a pointer that contains an address. Addresses can be manipulated mathematically; you can subtract one from another, you can add integers to them, and so on. Their legal operations indicate that they are "fancy numbers" that index into the "array" that is the virtual address space of the process.

Guido Domenici
That's talking about references rather than "pass by reference" - they're related but different concepts.
Jon Skeet
+26  A: 

Neither Java nor C has pass-by-reference. They are both strictly pass-by-value.

Pass-by-reference semantics mean that when you change the value of the parameter in the method, the caller will see that change in the argument.

Now, you may be thinking: "But that's the case in Java! If I change an object during the method, the caller sees that change." The object isn't the parameter. The parameter is just the variable - and if you change the value of that variable, the caller won't see that. For example:

public void foo(Object x)
{
    x = null;
}

public void caller()
{
    Object y = new Object();
    foo(y);
    // y is still not null!
}

If the parameter were really passed by reference, y would be null afterwards. Instead, the value of y is just a reference, and that reference is passed by value. It's confusing because the word "reference" is in both terms, but they're different things.

You may want to look at my article about C# parameter passing to see what would be possible if Java did have pass-by-reference semantics, as C# does when (and only when) you use the ref keyword.

You may also want to look at the comments to my Stack Overflow answer related to the topic.

Jon Skeet
Very, very true. This is one of the most misunderstood aspects of programming I have ever seen.
Simucal
Yes, the reference being passed by value is one of the first things that hung me up in C#
Ed Swangren
Wow! Thanks Jon, excellent answer!
Botond Balázs
This shows what Joel (The Joel) said about people - that they either grok pointers or they dont. To grok pointers, you have to be able to differentiate the "reference", and the other reference =)
Chii
+6  A: 

I thought the difference was that in Java all passing of objects is done with pointers automatically, where as in C one has to actually sprinkle little asterisks and ampersands here and there.

Conceptional, that's quite right. If we are pedantic (and that's a good thing), we can even say objects are not passed at all in Java. What is passed is only ever the "pointer", which in Java is called the reference. All indirection is done automatically. So when you do "objref->foo" instead of "objref.foo" in C and can't use the dot because you work with a pointer, in Java you can still use the dot because it doesn't know anything else to access members anyway. In C, you can pass the pointer (and here, it is actually called pointer) and you can pass the object itself, in which case a copy is passed. In C, you access the object that a pointer refers to by indirection using the star or "->". In Java, the only way objects are accessed anyway are using the dot (objref.member).

If we are pedantic again (now more important again), neither in Java nor in C there is "pass by reference". What we pass in Java is the reference/pointer to the object and in C we either pass a copy of the object (obvious case) or we pass again just a copy of a pointer to the object. So in both cases - Java and C - what we pass are the addresses of the objects. Not talking about primitive java types, which are copied in both Java and C - even though you can pass their address in C too, there is no difference between an aggregate type (i.e a struct) and a "primitive type" in C in that regard.

Johannes Schaub - litb
A: 

i m not sure about java but in C# or VB.net you can pass by value or by refrence

example passing by refrence

    static void Main(string[] args)
    {
        int x = 1;
        Foo(ref x);
        Console.WriteLine(x.ToString());//this will print 2
    }

    private static void Foo(ref int x)
    {
        x++;
    }

notice that x is equal to 1 but when you call the method Foo and passing x by refrence when x is increased by one in Foo the original value is increased too

Yassir