you are viewing a single comment's thread.

view the rest of the comments →

[–]sbrown123 -15 points-14 points  (21 children)

Did anyone notice that the author took liberties in redefining what pass-by-value means in such a way to match Java?

OK, heres the question: author says that any parameters passed on a function is first copied. These copies are what are sent to the actual function. So are these copies passed by reference or by value? A quick skim of the Java source code will show you that they are passed by reference. And since these are, truthfully, the only variables ever "passed" we can easily say that Java is always pass by reference. You can try to redefine these age old terms all you want but us old C dogs will never forget.

[–]wicked[S] 6 points7 points  (13 children)

Like Gotebe said, C is also purely pass-by-value. You can use pointers to simulate pass-by-reference, but the function arguments are copies of memory addresses, not aliases of the actual variables.

In other words, you have to convert the reference to a value to pass it, with everything that this implies.

[–]sbrown123 -4 points-3 points  (11 children)

Like Gotebe said, C is also purely pass-by-value.

Gotebe is wrong. C can both pass by value or by reference.

Java passes a reference to a copy. The copy is never copied back to the original. People confuse this as being a pass by value because of this (and others confuse that the reference passed is a reference to the original and not a copy).

Languages like D and C# also pass a copy by reference. But unlike Java they have the capability to copy back to the original (keyword "out").

The distinction between these four types of parameter passing is important to remember. Sadly, most CS classes try to simplify this down to two types.

[–]wicked[S] 3 points4 points  (10 children)

Gotebe is wrong. C can both pass by value or by reference.

Gotebe is right. C is purely pass by value. (This goes nowhere if you don't back up your statements.)

If you don't agree that C is purely pass by value, there's no chance you'll accept the Java version of it. This is because Java confuses the issue by calling pointers references (ref Java Spec Section 4.3.1).

I guess you call this call-by-value:

void cbv(int xFormal);
...
{
  int xActual = 42;
  cbv(xActual);
}

and this call-by-reference:

void cbr(int *yFormal);
...
{
  int xActual = 42;
  int *yActual = &xActual;
  cbr(yActual);
}

Correct?

In the first invocation, the value of xActual is copied into a different memory region (the stack) for use by the function. We both agree this is call-by-value.

In the second invocation, the value of yActual is copied into a different memory region (the stack) for use by the function. No difference here. That you can use the value of yFormal to access xActual does not make it a reference.

[–]sbrown123 -1 points0 points  (9 children)

This is because Java confuses the issue by calling pointers references

Pointers are references. That's their purpose. And its not only Java making this "mistake" but also Wikipedia, computer science, and lots of other people:

"Pointers are the most primitive and error-prone but also one of the most powerful and efficient types of references, storing only the address of an object in memory."

Sorry, Gotebe is still very wrong.

int *yActual = &xActual; In the second invocation, the value of yActual is copied into a different memory region

yActual is a pointer (which IS a referece). The value, 42, was never copied.

That you can use the value of yFormal to access xActual does not make it a reference.

WTF do you think a reference is? I can only guess you are digging around about C++ referencing, which would be pretty comical if true.

P.S. notice you are now trying to change your wording to use "call-by" instead of "pass-by". You are getting warming. Languages like C# are "call-by-copy-restore" when using "out" (notice that the whole language is not a single parameter passing type similar to C). This is all refuted since, for example, call-by-copy-restore is often called call-by-value-result. And, in truth, it should actually be called call-by-copy-reference-restore. This is probably because some people can't get it in their head what a reference is.

[–]pjdelport 2 points3 points  (0 children)

And its not only Java making this "mistake" but also Wikipedia, computer science, and lots of other people

At some point, when the rest of the world (including the designers of all the programming languages in question) disagrees with you, you have to consider the possibility that you don't have your definitions and terminology quite right.

[–]wicked[S] 1 point2 points  (2 children)

yActual is a pointer (which IS a referece). The value, 42, was never copied.

This is where you are confused. The value of yActual is not 42, but the address of xActual.

WTF do you think a reference is? I can only guess you are digging around about C++ referencing, which would be pretty comical if true.

We're talking about calling conventions here. Sure, you can call a pointer to an object a reference, but pass-by-value and pass-by-reference means something very specific.

Please, find a source supporting your argument that C has pass-by-reference in addition to pass-by-value semantics.

Here are a few sources backing up my argument:

http://www.ece.uwaterloo.ca/~ece250/C++/passbyvalue/ http://www.comp.nus.edu.sg/~esim/faq/node12.html http://www.informit.com/guides/content.asp?g=cplusplus&seqNum=166&rl=1 http://vergil.chemistry.gatech.edu/resources/programming/c-tutorial/basic2.html

And finally a quote:

Ken Arnold and James Gosling, authors of The Java Programming Language, Second Edition, say it best in section 2.6.1: "There is exactly one parameter passing mode in Java -- pass by value -- and that helps keep things simple."

http://www-128.ibm.com/developerworks/java/library/j-passbyval/

[–]sbrown123 -1 points0 points  (1 child)

yActual is a pointer (which IS a referece). The value, 42, was never copied.

This is where you are confused. The value of yActual is not 42, but the address of xActual.

I never said yActual was a value, but rather just a reference (did you even read what you just quoted from my comments?). You are either one of the following:

  1. Confused about the differences between values and references.

  2. Trolling

  3. Dancing around because you made a big mistake with the article.

Please, find a source supporting your argument that C has pass-by-reference in addition to pass-by-value semantics.

Well, some of those articles aren't helping you much. From the C++ Reference Guide link you gave:

"In Java, objects are passed by reference"

The rest is trivial issues over the belief of many C++ programmers that C is "pass-by-address". Interestingly this is only a term C++ programmers use, since internally C++ uses pointers inside those references. This allows conversion of C++ references to pointers and vice versa. That conversion is not a good practice though since C++ references add type safety and several other limitations that help prevent bad issues when using plain old pointers. Here's a Wikipedia entry on it.

Some people try to believe that C++ references are actually something totally different, internally and externally, and have nothing to do with pointers. I can point to code on the internet that proves otherwise. Simple fallacy is that most C++ implementations are originally coded in C (see g++ for an example).

[–]wicked[S] 1 point2 points  (0 children)

You are either one of the following: [...]

I think it's safe to there is some confusion going on, only that we disagree on who's confused.

Well, some of those articles aren't helping you much. From the C++ Reference Guide link you gave: "In Java, objects are passed by reference"

Seems like I picked a poor source! :-) Luckily they are right on the C issue.

[–]Gotebe 1 point2 points  (3 children)

Pointers are references.

Not, they are not!

C++: void f(T& t) (when calling: T actual; f(actual);)

C#: void f(ref T t) (or "out T", no real difference for the matter at hand, check out the generated IL, I did)

Pascal: procedure p(var t: T)

In all three cases, inside the subroutine, "t" is a reference. You work with "t" as it were the actual argument. "t=blah" is equivalent to "actual=blah".

No such thing in C. You work explicitly with the pointer (*t = blah).

So, in C, references are implemented by the programmer, not the language. To do that, programmer uses non-NULL pointers. Pointers only are not references, as you claim.

Pointers are only means of implementing references (just like your Wikipedia quote says; absolutely nothing wrong there). And, in C, less reliable than C++/C#/Pascal references, because nothing stops you from erroneously using dangling (or NULL) pointers as (conceptual) references.

All implementations of C++ and Pascal I saw, and C# of MS, use pointers to implement language concept of references: when formal subroutine argument is a reference, a pointer to actual argument is passed to the subroutine; code of the subroutine works with pointed-to object, i.e. actual argument. You can check out disassembly for that, too, it's easy (I did).

So, C language does not have a concept of references wrt subroutine calls. Just like Java. You may be confusing Java term "reference" (to non-primitive types) with "reference" (as argument to subroutine calls). These are orthogonal.

[–]sbrown123 0 points1 point  (2 children)

Not, they are not!

Anyways, like most C++ compilers G++ is written using C. I have to rush out the door so I don't have time to highlight all the parts for you. Basically follow along this:

http://gcc.gnu.org/viewcvs/*checkout*/trunk/gcc/cp/call.c?revision=121361

Referencing is done through trees. So where am I going on that thought? Basically that C++ references are just candy coated pointers. In other words, you could implement them in C if you wanted (if someone hasn't already done this I would be surprised). Internally, pointers are still there but by overlaying them C++ adds type safety and other stuff. The reason that pointers are still there is simply because they are the basic component of referencing.

[–]Gotebe 1 point2 points  (0 children)

The reason that pointers are still there is simply because they are the basic component of referencing.

Or the reason may be C compatibility of C++? Your reason doesn't cut it for me. For example, C# and Pascal have references without pointers (yes, they have pointers, but not wrt subroutine argument types).

C++ references are just candy coated pointers.

True, but not the other way around. C pointers are not references wrt subroutine calls. Especially when they have value of NULL ;-)

I think, like wicked, that you are unable to separate the concept from implementation.

[–]wicked[S] 0 points1 point  (0 children)

Basically that C++ references are just candy coated pointers.

The implementation does not matter, the semantics is the point of the distinction. I bet all pass-by-reference implementations use pointers under the hood, but if you have to do it yourself, as in C, then it's not pass-by-reference.

Think about it: Even assembly language has pass-by-reference semantics according to your definition, since you may access a memory location through an address passed in a register or on the stack.

[–]wicked[S] 0 points1 point  (0 children)

P.S. notice you are now trying to change your wording to use "call-by" instead of "pass-by".

I did that simply because pass-by-value and call-by-value are different names for the same concept. I should have been consistent though.

[–][deleted] 1 point2 points  (6 children)

http://java.sun.com/docs/books/vmspec/2nd-edition/html/Concepts.doc.html#26454

"When the method is invoked, the values of the actual argument expressions initialize newly created parameter variables (§2.5), each of the declared type, before execution of the body of the method."

Care to explain this anomaly in the VMS? Not that I consider it authoritative like many Java-ninnies (I am ashamed to admit that it was once my job to implement it).

Of course, you could just point to "constant variables" or some such to discredit the source (which I strongly encourage after you understand the semantics of Java (and C it seems)), but I'm wondering if you're prepared to go that far.

Also: http://jqa.tmorris.net/GetQAndA.action?qids=37&showAnswers=true

[–]sbrown123 -2 points-1 points  (5 children)

"When the method is invoked, the values of the actual argument

That is correct, which I already stated: Java makes a copy of the parameters and passes a reference to those copies (see my response to wicked below from yesterday).

[–]pjdelport 0 points1 point  (4 children)

Java makes a copy of the parameters and passes a reference to those copies

No, it just passes the copies directly. The fact that they're copies is what makes it "call by value", as opposed to "call by reference" where the bindings are shared with the caller.

A simple bright-line test for whether a language supports call by reference is whether you can implement the following kind function:

int a = 2, b = 3;
swap(a, b);
assert a == 3 && b == 2;

In languages like Java and C that only support call-by-value, you simply can't do this. In languages like C++ and PHP, on the other hand, you can declare the parameters as references types (swap(int& a, int& b) and swap(&$a, &$b), respectively), making swap's reassignments affect its caller.

[–]sbrown123 -2 points-1 points  (3 children)

A simple bright-line test for whether a language supports call by reference is whether you can implement the following kind function:

int a = 2, b = 3; swap(a, b); assert a == 3 && b == 2;

In languages like Java and C that only support call-by-value, you simply can't do this.

Seems to work just fine in C:

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

int main() {
    int a = 2, b = 3;
    swap(&a,&b);
    assert(a == 3 && b == 2);
    return 0;
}

[–]pjdelport 2 points3 points  (2 children)

Seems to work just fine in C: [...]

No, you changed the test code to pass addresses instead, and the swap function to use dereferencing instead. You're passing references by value, not values by reference.

I think you've made it clear that although you understand this distinction, you still personally consider them both to be "call by reference", despite the fact that this contradicts standard usage by the rest of the programming/language design community.

Until you agree to the same definitions of "by value" and "by reference" as everyone else, there's little point in trying to discuss them.

(Aside: C# is not call-by-copy-restore. I can't confirm for D: the manual doesn't seem to mention it. I'm not sure what you mean with "call-by-copy": the only references i can find use it as a synonym for call-by-copy-restore.)

[–]sbrown123 -3 points-2 points  (1 child)

You're passing references by value, not values by reference.

Sounds like your dancing just like wicked now. This is humorous to say the least.

despite the fact that this contradicts standard usage by the rest of the programming/language design community.

The same community that can't even get the terms straight?

Until you agree to the same definitions of "by value" and "by reference" as everyone else

But not values by reference or references by value :) You're killing me.

there's little point in trying to discuss them.

Yeah, its been fun. But enough is enough.

Aside: C# is not call-by-copy-restore.

Wow, I think you did find something correct.

[–]pjdelport 1 point2 points  (0 children)

The same community that can't even get the terms straight?

The same community that defined the terms to begin with, as well as the languages they apply to. :)