Call by Value and Call by Reference in C - Page 1
Forum section: electronics / projects

author: OptymizeSoham
author_rank: Newbie
timestamp: June 20, 2022, 12:58:23 pm
content: I'm trying to understand the conceptual difference between call by reference, value, and name.So I have the following pseudocode:Code:foo(a, b, c){b =b++;a = a++;c = a + b*10}X=1;Y=2;Z=3;foo(X, Y+2, Z);What's X, Y, and Z after the foo call if a, b, and c are all call by reference? if a, b, and c are call-by-value/result? if a, b, and c are call-by-name?Another scenario:Code:X=1;Y=2;Z=3;foo(X, Y+2, X);I'm trying to get a head start on studying for an upcoming final and this seemed like a good review problem to go over. Pass-by-name is definitely the most foreign to me.Please add your valuable insights.

author: moffy
author_rank: Super Contributor
timestamp: June 20, 2022, 02:04:47 pm
content: The values of a=1, b=2, c=3 after foo(a, b, c) are the same as before the call, no change. That is because foo(a, b, c) creates local copies of a, b, c and then discards them unless they are somehow returned after foo ends.However if foo is written as:void foo(float *a, float *b, float *c){*b = (*b)++;*a = (*a)++;*c = *a + (*b)*10;}it is called as:foo(&a, &b, &c);Then the operations on a, b, c are stored in the original variables, because foo doesn't create duplicate local variables but uses the original, passed by reference variable.

author: Siwastaja
author_rank: Super Contributor
timestamp: June 20, 2022, 02:25:32 pm
content: C is easy: there is no concept of call by reference, at all! Calls are always by value.Now, you can pass apointer, then this pointer will still beby value.If you pass int* to a function, int*, aka the pointer, aka the memory address, will be passed by value, meaning it's a copy, you can modify it within function and changes won't be visible.Now if you dereference that pointer and go modifying the data it points to, then this is different. These changes are visible to others, too.Add to this the confusion caused by C++, where youdohave the possibility to call by reference, and it isn't even visible from the caller-side syntax, so you might do that unknowingly by accident. This doesn't exist in C.

author: moffy
author_rank: Super Contributor
timestamp: June 20, 2022, 02:34:36 pm
content: Yes you are right, I mixed up my terms, it is call by pointer not reference.

author: T3sl4co1l
author_rank: Super Contributor
timestamp: June 20, 2022, 03:25:41 pm
content: A point of confusion may be that C more or less predates modern notions of references and object orientation.C is... certainly a much higher level than ASM, but it's still not too distantly related to it -- statements can be read as sequences of operations of a virtual machine, which is then implemented (by the compiler) as native ASM. It's very much imperative and procedural. The compiler doesn't much care what you're doing with objects -- the notion of an "object" is very thin, just memory allocations known at compile/link time -- and, as long as what you're doing meets the language standard, the compiler will simply do as told. Want to go munge some kernel memory? No problem! If your platform has memory protection, the OS at least may stop you with a (run time) segmentation fault.Whereas OOP, very specifically and intentionally does away with pointers -- which are inherently unsafe, as used in C -- and instead object references are handled exclusively by the compiler, and can only be manipulated in certain allowed ways. Thus, in Java for example, about the worst you should be able to do is a nullpointer exception -- which is to say, an uninitialized variable. You can't arbitrarily assign garbage to the reference: that's a type error. You can't place/allocate arrays arbitrarily, or access uninitialized memory as if it were an array; all must be declared, allocated, and initialized. (Under the hood, type is often stored in the object itself, so that, while you can typecast to a lower (inherited) type, like Object -- the VM/runtime can still check what it is, and do certain allowed conversions (like using Java's Integer object as an integer (primitive)).And OOP can free us from some of the burdens of procedural programming; we can instead describe what we want done, and then let the interpreter/compiler figure out how that should be done by the underlying machine.So, indeed, when we want to do call-by-reference in C -- it doesn't exist, we must go out of our way to recreate that functionality. We do this by passing pointers, which allow the function to modify the memory underlying those objects. Which is as others have said above.Under the hood, we know OOP is really doing the same thing -- a reference is a pointer to an object -- but we cannot read or modify that pointer directly, at least not through any intended means. And any such violation is almost certainly a bug in the interpreter -- often an extremely serious one at that, as the language trusts itself by default, so does not usually employ protection between objects or functions or what have you -- an errant pointer, used carefully, likely can pwn the system.C++ of course is different, having all of these, and more. The tradition for C and immediate relatives tends to be, give you more guns you can possibly handle, and let you foot-gun yourself if you so choose. They can be used quite powerfully, but they also fail in fantastically embarrassing ways; often from quite subtle mistakes.Mind -- comparisons between C and other paradigms, safety, bugginess and such -- don't take this as a judgement call, that's simply how it is. There are good and bad aspects to everything; we must simply deal with them, how ever they may come.Tim