Confused between call by ref and call by value in my code - c

Just started C this year in my uni and I'm confused whether my function call is by reference or value.
I created an empty array in main called freq_array and this is passed as an argument when the function frequency is called. So since after the func call, the empty array will now contain values, this is considered call by reference? I read in other websites that call by reference uses pointers so I'm slightly confused. Thank you.
void frequency(int[]); //prototype
frequency(freq_array); //func call
void frequency(int fr[arraysize]) //arraysize = 18
{
int n;
for (n=0; n<10; n++)
{
fr[n]= 100 * (n + 1); //goes from 100Hz - 1000Hz
}
for (n=10; n<18; n++) //goes from 2000Hz - 9000Hz
{
fr[n]= 1000 * (n - 8);
}
}

In theory, C only has "pass by value". However, when you use an array as parameter to a function, it gets adjusted ("decays") into a pointer to the first element.
Therefore void frequency(int fr[arraysize]) is completely equivalent to void frequency(int* fr). The compiler will replace the former with the latter "behind the lines".
So you can regard this as the array getting passed by reference, but the pointer itself, pointing at the first element, getting passed by value.

For arguments, you can't pass arrays only pointers. When the compiler sees the argument int fr[arraysize] it will treat is as int *fr.
When you do the call
frequency(freq_array);
the array decays to a pointer to its first element. The above call is equal to
frequency(&freq_array[0]);
And C doesn't have pass by reference at all. The pointer will be passed by value.
However using pointers you can emulate pass by reference. For example
void emulate_pass_by_reference(int *a)
{
*a = 10; // Use dereference to access the memory that the pointer a is pointing to
}
int main(void)
{
int b = 5;
printf("Before call: b = %d\n", b); // Will print that b is 5
emulate_pass_by_reference(&b); // Pass a pointer to the variable b
printf("After call: b = %d\n", b); // Will print that b is 10
}
Now, it's important to know that the pointer itself (&b) will be passed by value.

Related

why results of these two functions are different?

I expected results are same. Two functions do same thing but
why they are different?
I think its related to pointers.
void changer(int n){
n = 20;
}
void arrayChanger(int n[]){
n[0] = 20;
}
int main()
{
int a = 5;
int ar[1] = {5};
changer(a);
arrayChanger(ar);
printf("%d\n",a);
printf("%d\n",ar[0]);
return 0;
}
Arguments are passed by value unless the argument is specifically declared to be passed by reference, and arrays will decay to a pointer to their first element when passed to functions.
The function changer does not update the actual variable a since it only receives its value, not the variable itself.
If you want to update a value in a function call, you need to pass it by reference:
void make20(int *a)
{
*a = 20;
}
The call would then look like:
int n = 5;
make20(&n);
// now n = 20
In changer(a), you pass an int as the parameter. This int is passed by value. That means that when changer executes, it simply receives the int 5 as a parameter and sets the parameter to 20. However, since the parameter is passed by value, there is no change to the parameter outside of the function.
In arrayChanger(ar), you pass an array as the parameter. As mentioned by Osiris, when passing an array to a function, it 'decays' to a pointer to the first element of said array. Therefore, in arrayChanger, you set the value at the pointer to 20. This means that after execution, the value at the pointer (which has remained constant) is now 20 rather than the original 5.

How does the compiler understand whether the given function does a pass by value or pass by referene?

How does the C compiler understand whether the given function does a pass by value or pass by reference?
what will happen if the pointer of a variable is passed as integer (as pass by value) to a function ? OR is this possible in C ?
ie: the address of a variable is copied to another variable(int) and that variable is passed to a function. here the called function will get an address as normal integer parameter. Is this possible in C? if not why?
In C it is possible only the pass by value (by reference is supported only in C++).
Both a standard variable and a pointer variable are passed by value. So, the compiler must not make any check about reference or value.
standard variables and pointer variables are same, both store values, but a pointer variable can store only an address value and supports the dereferencing operator '*', this operator get the value pointed by the pointer variable.
Thanks to this, when you pass by value (C support only by value) a pointer variable, the value of the pointer variable is copied in a local pointer variable (instanced in the function stack) this variable is the pointer argument of the function. So you can access to address value copied in the local pointer variable using the dereferencing operator.
Added comments 08/22/14
I can better explain with a example:
void FuncSet10(int* PtrArgument)
{
// The PtrArgument is a local pointer variable
// it is allocated in the stack. The compiler
// copies the MyIntVariable address in this variable
// Using dereferencing operator I can access to
// memory location pointed by PtrArgument
*PtrArgument = 10;
}
void FuncSet20(int IntArgument)
{
// The IntArgument is a local variable
// allocated in the stack. The compiler
// copies the MyIntVariable address in this variable
// this code emulates the dereferencing operator
// and so poiter mechanism.
*((int*)IntArgument) = 20;
}
void FuncMovePointer(int* pointer)
{
int a = *pointer++; // now a contains 1
int b = *pointer++; // now b contains 2
int c = *pointer++; // now c contains 3
printf("a contains %d\n", a);
printf("b contains %d\n", b);
printf("c contains %d\n", c);
// The *Ptr now points to fourth (value 4) element of the Array
printf("pointer points to %d\n", *pointer);
}
int _tmain(int argc, _TCHAR* argv[])
{
int Array[] = {1, 2, 3, 4}; // Array definition
int* pointer = Array; // pointer points to the array
int MyIntVariable;
// First example for explanation of
// the pointer mechanism and compiler actions
// After calling this function MyIntVariable contains 10
FuncSet10(&MyIntVariable);
printf("MyIntVariable contains %d\n", MyIntVariable);
// After calling this function MyIntVariable contains 20
// This code emulate pointer mechanism
FuncSet20((int)&MyIntVariable);
printf("MyIntVariable contains %d\n", MyIntVariable);
// Second example to demonstrate that a pointer
// is only a local copy in a called function
// Inside function the pointer is incremented with ++ operator
// so it will point the next element before returning by function
// (it should be 4)
FuncMovePointer(pointer);
// But this is not true, it points always first element! Why?
// Because the FuncMovePointer manages a its local copy!
printf("but externally the FuncMovePointer it still points to first element %d\n", *pointer);
return 0;
}
I hope that above code can help better your understanding.
Angelo
How does the C compiler understand whether the given function does a
pass by value or pass by reference?
For your information C not understand about pass by reference. You can send pointer to variable.
what will happen if the pointer of a variable is passed as integer (as
pass by value) to a function ?
Passing the pointers to a variable and the accessing it using dereferencing within the function.So By passing a pointer to a function you can allow that function to read and write to the data stored in that variable.
For example
void myfunc( int *myval ) // pointer "myval" point address of "locvar"
{
*myval = 77; //place value 77 at address pointed by "myval"
}
int main()
{
int locvar=10; //place value 10 at some address of "locvar"
printf("locvar = %d\n",locvar);
myfunc(&locvar); // Here address of "locvar" passed
printf("locvar = %d\n",locvar);
return 0;
}

What is byValue and byReference argument passing In C? [duplicate]

This question already has answers here:
What's the difference between passing by reference vs. passing by value?
(18 answers)
Closed 9 years ago.
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 :)
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.
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*/
}
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
}
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
...
}
in-depth explanation
whenever a program loads, it gets a memory area so called address space which gets divided into various regions
code/text : contains the statements of program (collections of statements).
global : contains the global variable if any.
constant : used for constant or literal storage.
heap : used for dynamic memory need.
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.
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.

statically allocated array as function argument in C

Can I do this in C:
void myFunc(int *vp) {
// do some stuff with vp
}
int main() {
int v[5] = {1,2,3,4,5};
myFunc(v);
return 0;
}
I mean, what would be the correct? myFunc(&v); ?
Thanks!!
Arrays decay to pointers when you pass them as arguments. However, array decay is not the same as taking the address of an array.
"Decay" is how some types are transformed when passed as function arguments. Even though v's type is int [5], it becomes int* when you pass it to a function. This is a behavior a lot of people don't like, but there's nothing to do about it.
Note that, on the other hand, the type of &v is int (*)[5], that is, a pointer to an array of 5 integers. This type doesn't decay, that is, it doesn't transform automatically into another type if you pass it as a function parameter (and that's also why it wouldn't work if you used it in your example, since you need a pointer to integers, not a pointer to an array of integers).
The "correct" thing to do (assuming decay is OK) is to do myFunc(v), just as you're doing in your snippet. Keep in mind that you lose array bounds information when you do it.
Yes ... Your code is correct.
Here v==&v[0] array name is equal to address of first element of array
myFunc(v);
passing array name as argument that means you are passing address of first element in array.
void myFunc(int *vp)
Here you are using pointer. which store the address of first element of array which is passed so you can access the block which is covered with the array.by incrementing the pointer location.
And
myFunc(&v);
&v==&&v[0];
&v is address of address of array first element.
Now
void myFunc(int *vp)
Here You got address of address of array first element, This is not pointing to array. Instead pointing some memory location.Now You can't access the array by incrementing the pointer.
Your code is correct It will work....
But you should take extra care to check the boundary condition.
Please look through the code.
void myFunc(int *vp) {
vp[5] = 30;
}
int main() {
int v[5] = {1,2,3,4,5};
int a = 10;
printf("Value of a before fun call %d\n", a);
myFunc(v);
printf("Value of a before fun call %d\n", a);
return 0;
}
similarly
void myFunc(int *vp) {
vp[5] = 30;
myFunc2(vp);
}
void myFunc2(int *vp) {
vp[6] = 30;
}
int main() {
int v[5] = {1,2,3,4,5};
int a = 10;
printf("Value of a before fun call %d\n", a);
myFunc(v);
printf("Value of a before fun call %d\n", a);
return 0;
}
This will result in segmentation fault due to stack curruption. Since local variables are in stack.

Double pointers are also sometimes employed to pass pointers to functions by reference

" Double pointers are also sometimes employed to pass pointers to functions by reference "
can somebody can explain me the above statement, what exactly does point to function by reference means ?
I believe this example makes it clearer :
//Double pointer is taken as argument
void allocate(int** p, int n)
{
//Change the value of *p, this modification is available outside the function
*p = (int*)malloc(sizeof(int) * n);
}
int main()
{
int* p = NULL;
//Pass the address of the pointer
allocate(&p,1);
//The pointer has been modified to point to proper memory location
//Hence this statement will work
*p=10;
//Free the memory allocated
free(p);
return 0;
}
It means that you have a function that takes a pointer pointer (type int ** for example). This allows you to modify the pointer (what data it is pointing to) much in the way passing a pointer by reference would allow.
void change (int *p) {*p = 7;}
void Really_Change (int **pp) {*pp = null;}
int p = 1;
int *pp = &p;
// now, pp is pointing to p. Let's say it has address 0x10;
// this makes a copy of the address of p. The value of &p is still 0x10 (points to p).
// but, it uses that address to change p to 7.
change(&p);
printf("%d\n", p); // prints 7;
// this call gets the address of pp. It can change pp's value
// much like p was changed above.
Really_Change(&pp);
// pp has been set to null, much like p was set to 7.
printf("%d\n", *pp); // error dereference null. Ka-BOOM!!!
So, in the same way that you can pass a pointer to an int and change the value, you can pass a pointer to a pointer and change its value (which changes what it points to.)
I'll try to explain with both code and plain english :). The explanation may get long, but it will be worth the while.
Suppose we have a program, running its main() function, and we make a call to another function that takes an int parameter.
Conceptually, When you pass a variable as a parameter to a function, you can do so in (roughly speaking) two ways: by value, or by reference.
"By value" means giving the function a copy of your variable. The function will receive its "content" (value), but it won't be able to change the actual variable outside its own body of code, because it was only given a copy.
"By reference", on the other hand, means giving the function the actual memory address of our variable. Using that, the function can find out the variable's value, but it can also go to that specified address and modify the variable's content.
In our C program, "by value" means passing a copy of the int (just taking int as argument), and "by reference" means passing a pointer to it.
Let's see a small code example:
void foo(int n) {
n = 10;
printf("%d\n", n);
}
int main() {
int n = 5;
foo(n);
printf("%d\n", n);
return 0;
}
What will the output of this program be? 10 10? Nope. 10 5! Because we passed a copy of the int, by value and not by reference, foo() only modified the number stored in its copy, unable to reach main()'s copy.
Now, if we do it this way:
void foo(int* n) {
*n = 10;
printf("%d\n", *n);
}
int main() {
int n = 5;
foo(&n);
printf("%d\n", n);
return 0;
}
This time we gave foo() our integer by reference: it's actual memory address. foo() has full power to modify it by accessing it's position in memory, foo() and main() are working with the same copy, and so the output will be 10 10.
As you see, a pointer is a referece,... but also a numerical position in memory. It's similar to an int, only the number contained inside is interpreted differently. Think of it this way: when we pass our int by reference, we're passing an int pointer by value!. So the same by value/by reference logic can be applied to pointers, even though they already are references.
If our actual variable was not an int, but an int reference (pointer), and we wanted main() and foo() to share the same copy of that reference so that foo() can modifiy it, what would we do? Why of course, we'd need a reference to our reference! A pointer to a pointer. That is:
int n; /* integer */
int* n; /* integer reference(pointer). Stores an int's position in memory */
int** n; /* reference to integer reference, or double pointer.
Stores int*'s memory address so we can pass int*s by reference. */
I hope this was useful.

Resources