0

I dont understand what this means. If I were to try and guess I'd say byValue argument passing is when you pass an argument based on the value of an variable, so I'm thinking:

if (a == 1){
 PassAnArgumentOrSomething()
}

However that is probably wrong :/

As for byReference, I have no idea.

If anyone can help me out that be awesome of you :)

user2727356
  • 25
  • 1
  • 4
  • @Basile Starynkevitch The referenced post, though applicable, is a general discussion (language agnostic). None of the high ranked answers are C specific. This question, tagged C, merits an answer that covers the details of array arguments, which sadly is a Holy War. – chux - Reinstate Monica Dec 07 '13 at 18:17

6 Answers6

4

With the exception of arrays and functions (see below), C always passes arguments `by value': a copy of the value of each argument is passed to the function; the function cannot modify the actual argument passed to it:

void foo(int j) {
  j = 0;  /*  modifies the copy of the argument received by the function  */
}

int main(void) {
  int k=10;
  foo(k);
  /*  k still equals 10  */
}

If you do want a function to modify its argument you can obtain the desired effect using pointer arguments instead:

void foo(int *j) {
  *j = 0;
}

int main(void) {
  int k=10;
  foo(&k);
  /*  k now equals 0  */
}

This is sometimes known as `pass by reference' in other languages.

san45
  • 459
  • 1
  • 6
  • 15
2

There is no pass by reference in c language

Passing by value: means that you are creating a temporary copy of the variable and sending to the parameter.

Passing by reference(no such concept in c language): means that you are just giving another name to the original variable while calling and no temporary copy of the variable is being created.

Calling by value:

int foo(int temp)
{
    /.../
}
int main()
{
    int x;
    foo(x); /* here a temporary copy of the 'x' is created and sent to the foo function.*/

}

Calling by reference(no such concept in c language)

int foo(int& temp)
{
   /.../
}
int main()
{
    int x;
    foo(x); /* here no temporary copy of 'x' is being created rather the variable *temp* in the calling function is just another name of the variable a in the main function*/
}
Kaustav Ray
  • 744
  • 6
  • 20
1

Passing an argument by value means you are passing a copy:

void f(int x) 
{ 
    x = 7;
    // x is 7 here, but we only changed our local copy
}

void g()
{
    int y = 3;
    f(y);
    // y is still 3 here!
}

Passing an argument by reference means you are not passing a copy, but instead passing some way of referencing the original variable. In C, all arguments are pass by value, but what is typically done to get the same effect as passing by reference is to pass a pointer:

void f(int *x_ptr) { *x_ptr = 7; }

void g()
{
    int y = 3;
    f(&y);
    // y is 7 here 
}

Arrays are passed in such a way that it appears similar to pass-by-reference, however what is actually happening is more complicated. For example:

void f(int a[]) { a[0] = 7; }

void g()
{
    int b[3] = {1,2,3};
    f(b);
    // b[0] is 7 here! looks like it was passed by reference.
}

What is actually happening here is that the array b is implicitly converted to a pointer to the first element (this is known as decay). The int a[] notation for the parameter to f is actually syntactic sugar for a pointer. The above code is equivalent to:

void f(int *a) { a[0] = 7; }

void g()
{
    int b[3] = {1,2,3};
    f(&b[0]);
    // b[0] is 7 here
}
Vaughn Cato
  • 63,448
  • 5
  • 82
  • 132
  • It's not implicit at all. You're explicitly passing the first element. You can easily use `bar = foo(arr[7]);` to pass a different "head" of the array into the new function. – ciphermagi Dec 07 '13 at 14:45
  • @JonahNelson: I'm not sure what code you are referring to. In the case of `f(b)`, I wouldn't call this an explicit pass of a pointer to the first element of `b`. If I wanted to be explicit, I would write `f(&b[0])`. – Vaughn Cato Dec 07 '13 at 14:50
  • The only thing you're doing in the function declaration/definition is receiving *any* pointer of whatever type you declare. the function call makes an explicit passing of data. Since `arr == &arr[0]` passing arr makes a pointer to the first element. `arr + 7 === &arr[7]` and so you're making a new array with from a subset of the original. There's nothing implicit about it. – ciphermagi Dec 07 '13 at 14:55
  • 2
    @JonahNelson: If `arr` is an array, then it is not a pointer, it is an array. It is converted to a pointer when it is used like a pointer. This conversion is called decay, and it is implicit because it doesn't require any explicit code for this to happen. – Vaughn Cato Dec 07 '13 at 15:00
  • What does that have to do with the **index of the array** that you're passing? – ciphermagi Dec 07 '13 at 15:02
  • @LightnessRacesinOrbit Next you're going to try to tell me that the arrays don't have any indices, right? `f(b);` is the 0th index. `f(b[5])` is the fifth index. It's completely false to say that you're not passing any sort of index. – ciphermagi Dec 07 '13 at 15:14
  • @VaughnCato I'm pretty sure you and I aren't talking about the same thing. I think you're talking about the way that the processor treats the *passing* of data, while I'm talking about how it treats the *calling* of data. Your users must pass a specific element, or no element, which refers to the head of the original array. If another element is passed, that element becomes the head of the new array inside the called function. – ciphermagi Dec 07 '13 at 15:17
  • @JonahNelson: If `b` is an array of ints, and `f` takes a pointer to an int as a parameter, then calling `f(b[5])` would not be correct. You would need to use `f(&b[5])` or `f(b+5)`. – Vaughn Cato Dec 07 '13 at 15:25
  • Aye. I did leave off the address. – ciphermagi Dec 07 '13 at 15:26
  • @Jonah: `f(b); is the 0th index` No, this is wrong. `b` is an array. It is not the same as `&b[0]`, _despite array name decay from the former to the latter_. It is plain to see, lexically, that no index is being passed by the programmer. – Lightness Races in Orbit Dec 07 '13 at 15:59
0

Passing by value is passing the value itself; it makes a copy of the value, and any changes you make in the new function are NOT saved to the original variable:

void foo(int num)
{
    num = 5; // Does not save to the original variable that was passed when foo was called
...
}

Passing by reference is passing the location of the variable; it allows the new function to directly edit the original variable:

void bar(int * num)
{
    *num = 5; // Changes the variable in the original function
...
}
ciphermagi
  • 747
  • 3
  • 14
  • Note that this isn't actually passing by reference: you're still passing the value of the pointer to the function. – Kninnug Dec 07 '13 at 14:41
  • 1
    Yes. In C and, I believe, C++ there is no way to *actually* pass by reference. This is, however, the way that "by reference" is understood to those who use it in those languages. – ciphermagi Dec 07 '13 at 14:43
  • 1
    @JonahNelson What about *references* in C++ ? – zakinster Dec 07 '13 at 15:11
  • In c++, you have reference as well. Consider: int func(int &a) { ... } . &a is reference variable. No copy of passed variable is created. If you alter a's value inside the func, the altered value is seen by the caller as well. – teroi Dec 07 '13 at 15:18
0

in-depth explanation

whenever a program loads, it gets a memory area so called address space which gets divided into various regions

  1. code/text : contains the statements of program (collections of statements).
  2. global : contains the global variable if any.
  3. constant : used for constant or literal storage.
  4. heap : used for dynamic memory need.
  5. stack : function used its for variable.

consider a function so defined as

void doSomething(int x)
{
   x++;
}//end of function

is called as doSomething(5) or doSomething(y) in another function or main function .

here x is local variable to function "doSomething". It gets its home (memory location) somewhere in stack region.

When doSomething(5) is called 5 gets copied to x's memory or doSomething(y) is called value/content of y (different memory location) gets copied to x's memory. Whatever operations applied on x, will not affect y 's content/value at all. Since its memory location is different.

Whenever execution flow reachs at end of function x dies/gets destroyed. Whatever value of x is not accessible/available. In short, update is lost and y is unaffected (Change is not reflected).

This is what so called Call by Value

Now Consider an another function so defined as

void doSomething(int *x)
{
    (*x)++;
}

is called as doSomething(&y)

here x is called pointer (conceptually called reference*).It will also gets home somewhere in stack region
When doSomething(&y) is called address of y gets copied to x's location block. Since this x is special variable so called pointer that holds address and it is said that x refers/points to y.

When (*x)++ is applied, here * is indirection operator which will bring whom x refer to the context ie. (*x)++ will indirectly change the value of y by 1. Nothing will happen to x's value itself.

Whenever execution flow reach at end of function *x dies/gets destroyed as expected but this time change is made to y (indirectly) which is still alive somewhere in stack region (change is reflected).

Also not that this time doSomething(&5) or doSomething(any literal) is not possible because it's illegal to get address of any literal.

This is what so called Call by Reference/Call by Pointer.

note that Call by Reference has another meaning in C++ but conceptually remains same.

The Mighty Programmer
  • 1,242
  • 12
  • 23
0

Let's look at the "calling" of functions first.

In C, the arguments to a function are typically "by value". Below, after calling sqrt(x), the value x is not changed for sqrt() received a copy of the value x, thus never gaining an ability to affect x.

y = sqrt(x);
// x did not change
printf("%f is the square root of %f\n", y, x);

Array parameters to a function appear to be "by reference". After fgets() is called, buf is expected to be altered. fgets() did not receive a copy of, but a "reference" to the char array. Thus fgets() could affect the contents of the array.

char buf[80] = { 0 };  // array 80 of char
printf("Before <%s>\n", buf);   // "<>"
fgets(buf, sizeof buf, stdin);
printf("After <%s>\n", buf);    // "<Hello World!>"

Let's now look at the "receiving" part: the function.

Function parameters of type double, int, struct types are received by value. The value of f here is the copy of the x above. Any changes made to f do not affect the x in the calling code.

double sqrt(double f) {
  double y;
  ... // lots of code
  return y;
}

Now comes the tricky bit and this is where there is lots of discussion in C.

The parameter s in fgets() below was not assigned the buf above (array 80 of char), instead s was assigned the pointer type derived from buf: address of the first element of an buf. By knowing the address of the array elements of buf (via s), fgets() affects what was printed above.

char *fgets(char * restrict s, int n, FILE * restrict stream) {
  // code
  s[i] = ThisAndThat();
  // code
  return s;
}

Let's now see how fgets() otherwise might be called:

char *p = malloc(80);
*p = '\0';
printf("Before <%s>\n", p);   // "<>"
fgets(p, 80, stdin); 
printf("After <%s>\n", p);    // "<Hello World!>"

In this 2nd example, p is a "pointer to char". It is passed by value to fgets(). fgets() received, via s, a copy of p.

The central idea: fgets() does not know if it received an "address of the first element of an array" or a copy of a "pointer to char". In both cases, it treats s as a "pointer to char".

Let's assume fgets() did the following. Before s being changed, it affects the data pointed to by s. Then s, the pointer, changed. s is a local variable and this assignment does not change the calling routines variables buf nor p.

char *fgets(char * restrict s, int n, FILE * restrict stream) {
  // lots of code
  s[0] = '\0';
  // more code
  s = NULL;
  return s;
}

Note: There are other issues such as passing functions as parameters and encapsulating arrays in structures to consider.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256