I thought that calling function by value will never work, and I should always use call by reference, but trying this code...
// call by value
#include<stdio.h>
int Add(int a, int b)
{
int c = a + b ;
return c ;
}
int main()
{
int x = 2 , y = 4 ;
int z = Add(x,y);
printf("%d\n",z);
}
output will be: 6
it works fine in both ways (call by value & call by reference),
// call by reference
#include<stdio.h>
int Add(int* a, int* b)
{
int c = *a + *b ;
return c ;
}
int main()
{
int x = 2 , y = 4 ;
int z = Add(&x,&y);
printf("%d\n",z);
}
output will be: 6
not like the famous swap function example - when calling by value it doesn't swap -
// call by value
#include <stdio.h>
void swap(int a, int b)
{
int temp;
temp = b;
b = a;
a = temp;
}
int main()
{
int x = 1 , y = 2;
printf("x = %d , y = %d\n", x,y);
swap(x, y);
printf("after swapping\n");
printf("x = %d , y = %d\n", x,y);
return 0;
}
.. it only worked calling by reference
// call by reference
#include <stdio.h>
void swap(int *a, int *b)
{
int temp;
temp = *b;
*b = *a;
*a = temp;
}
int main()
{
int x = 1 , y = 2;
printf("x = %d , y = %d\n", x,y);
swap(&x, &y);
printf("after swapping\n");
printf("x = %d , y = %d\n", x,y);
return 0;
}
So How can I judge if "calling by value" going to work or not ?!
So How can I judge that call by value method is valid or not ?!
Well, it depends on what your function is about to do.
In your above example, you only need the values of (x,y) for computing, but you never plan to change their value during your function. While call-by-reference will work in this case, it is unneccessary.
In the other (indirectly given) example you obviously want to change two variable's content (that is - swap it). You can access these variables from the main-function in your Swap-function, but how can you make the change persistent? That's only possible by call-by-reference, because you have to write the changed content into a variable that survives the function.
The following will not work:
// call by value
#include<stdio.h>
void Swap(int a, int b)
{
int c = a;
a = b;
b = c;
// from here on a, b, c will be destroyed
// therefore the change cannot be seen outside the function
}
int main()
{
int x = 2 , y = 4 ;
Swap(x,y);
printf("x: %d --- y: %d\n",x,y);
}
So as a rule to keep in mind:
If you want to make a change that's supposed to survive the function's end, use call-by-reference. If you just work with some data but do not want to (or must not) change their value, use call-by-value.
Related
I am solving the problem of swapping the value of two variables. I need to do it using a helper function. Now I've been studying the call-by-value and call-by-reference stuff.
My only confusion is when I'm passing the arguments to the swap function, why am I sending the address(&a, &b)? What actually happens when I'm sending the address instead of the value itself?
Here's the code
#include <stdio.h>
void swap(int a, int b) {
int temp;
temp = a;
a = b;
b = temp;
printf("After swapping values in function(using call by value) a = %d, b = %d\n",a,b);
}
void swapref(int *a, int *b) {
int temp2;
temp2 = *a;
*a=*b;
*b=temp2;
printf("After swapping values in function(using call by reference) a = %d, b = %d\n",*a,*b);
}
int main() {
int a = 10, b = 20;
printf("Before swapping the values in main a = %d, b = %d\n",a,b);
swap(a,b);
printf("After swapping values in main(using call by value) a = %d, b = %d\n",a,b);
swapref(&a,&b); // <-- This is the line I'm talking about
printf("After swapping values in main(using call by reference) a = %d, b = %d\n",a,b);
return 0;
}
In the above code, what actually happens in the swapref(&a, &b) line?
Passing the address is different than giving the value since you passe the exact memory case where your original variable (a and b) are stored. Like :
void swapref(int *a, int *b)
So when in the function you modify those value, you change the original ones.
Whereas passing variables values like :
void swap(int a, int b)
You're passing a copy of each variable, so the originals won't be touched.
swap() parameters are passed by copy, while swapref() ones are passed by reference (i.e. you pass the variable memory address, instead of its content).
* operator returns the value-pointed-to of a variable
& operator returns the address-of a variable
To better understand what happens, I suggest you to print their addresses
void swap(int a, int b) {
int temp;
temp = a;
a = b;
b = temp;
printf("After swapping values in function (using call by value) [%p]a = %d, [%p]b = %d\n", &a, a, &b, b);
}
void swapref(int* a, int* b) {
int temp;
temp = *a;
*a = *b;
*b = temp;
printf("After swapping values in function (using call by reference) [%p]a = %d, [%p]b = %d\n", &(*a), *a, &(*b), *b);
}
int main()
{
int a = 10, b = 20;
printf("Before swapping the values in main [%p]a = %d, [%p]b = %d\n", &a, a, &b, b);
swap(a, b);
printf("After swapping values in main (using call by value) [%p]a = %d, [%p]b = %d\n", &a, a, &b, b);
swapref(&a, &b); // <-- This is the line I'm talking about
printf("After swapping values in main (using call by reference) [%p]a = %d, [%p]b = %d\n", &a, a, &b, b);
return 0;
}
Output:
Before swapping the values in main [000000A6B03BF834]a = 10, [000000A6B03BF854]b = 20
After swapping values in function(using call by value) [000000A6B03BF800]a = 20, [000000A6B03BF808]b = 10
After swapping values in main(using call by value) [000000A6B03BF834]a = 10, [000000A6B03BF854]b = 20
After swapping values in function(using call by reference) [000000A6B03BF834]a = 20, [000000A6B03BF854]b = 10
After swapping values in main(using call by reference) [000000A6B03BF834]a = 20, [000000A6B03BF854]b = 10
As you can notice, the variables used in swapref() present the same addresses as the ones that are passed to the function.
As you can see by the output of your program:
After swapping values in function(using call by value) a = 20, b = 10
After swapping values in main(using call by value) a = 10, b = 20
After swapping values in function(using call by reference) a = 20, b = 10
After swapping values in main(using call by reference) a = 20, b = 10
The variables are not actually swapped. Whenever passing a something as a parameter, its value is copied into the argument.
void by_val(int i) {
i = 2;
// the variable i in main will NOT be changed,
// because this one is a copy
}
void by_ptr(int* i) {
// This will change the i in main, because we didn't copy its value,
// but copied the memory address of i variable in main.
*i = 2;
// Now we can make i point to an other variable than the main function i.
// This will not update i, but it will update num.
int num = 2;
i = #
*i = 3;
}
int main() {
int i = 1;
by_val(i);
printf("%d\n", i); // "1"
by_ptr(&i);
printf("%d\n", i); // "2"
}
So in your first swap function, the values of the copies of (main) a and b are being swapped, not the values of (main) a and b. But in your second function, the values of (main) a and b are swapped, because you passed the memory addresses of the (main). The * operator makes the program use the values in the variables, the memory address is pointing to.
It doesn't help that you're using the same names for different things. For the purpose of this answer, we're going to assume the variables in main are named x and y instead:
int main( void )
{
int x = 10, y = 20;
...
swap(x, y);
...
swapref(&x, &y);
...
}
That will make the following discussion easier to follow.
The formal parameters a and b in swap are different objects in memory from the local variables x and y in main.
When you call
swap(x, y);
in main, the expressions x and y are fully evaluated and the results of those evaluations (10 and 20, respectively) are passed to swap and copied into its formal arguments.
Since a and b are different objects from x and y, exchanging the values of a and b has no effect on the values of x and y.
Just like with swap, the formal parameters a and b in swapref are different objects in memory from the local variables x and y. When you call
swapref(&x, &y);
the expressions &x and &y are fully evaluated, and the results of those evaluations (the addresses of x and y) are passed to swapref and copied into the formal arguments a and b.
This means the following relationships are true:
a == &x // int * == int *
*a == x // int == int
b == &y // int * == int *
*b == y // int == int
Again, since a and b in swapref are different objects in memory from x and y in main, changing the values of a and b in swapref has no effect on x and y. However, when you write new values to the expressions *a and *b in swapref, you're not changing the values of a and b but rather what a and b point to, which in this case is x and y.
You can kinda-sorta think of *a and *b as aliases for x and y - they're alternate names for the same objects. Writing
temp = *a;
*a = *b;
*b = temp;
is equivalent to writing
temp = x;
x = y;
y = temp;
So, I was experimenting with assembly and pointers, so I decided to do a little extra, I made a new integer , d and assigned the function exchange to it:
#include <stdio.h>
int exchange(int *xp, int *yp, int *zp){
int x = *xp;
int y = *yp;
int z = *zp;
*xp = z;
*yp = x;
*zp = y;
}
int main(){
int a = 3;
int b = 12;
int c = 24;
exchange(&a, &b, &c);
printf("int a = %d, int b = %d, int c = %d : ", a, b, c);
int d = exchange(&a, &b, &c);
printf("\n int d = %d", d);
return 0;
}
So, when I do the exchange function , it works as intended, switching the values in the registers. Except. . . .d returned a weird number: 6356768.
I'm not sure why d returns that value, but I would be much obliged if somebody would explain how it happened.
Your problem is that you have not returned anything from exchange whose return type is int. Hence what you see is garbage for the value of d. Try returning a status flag like 1 for success.
#include <stdio.h>
int exchange(int *xp, int *yp, int *zp) {
int x = *xp;
int y = *yp;
int z = *zp;
*xp = z;
*yp = x;
*zp = y;
return 1;
}
int main(){
int a = 3;
int b = 12;
int c = 24;
exchange(&a, &b, &c);
printf("int a = %d, int b = %d, int c = %d : ", a, b, c);
int d = exchange(&a, &b, &c);
printf("\n int d = %d\n", d);
return 0;
}
You should see something like,
int a = 24, int b = 3, int c = 12 :
int d = 1
Let me know if this helps !!
Not a proper answer, just an interesting observation:
I added some printfs in your code:
#include <stdio.h>
int exchange(int *xp, int *yp, int *zp){
int x = *xp;
int y = *yp;
int z = *zp;
printf("xp = %p, yp = %p, zp = %p\n", xp, yp, zp);
*xp = z;
*yp = x;
*zp = y;
}
int main(){
int a = 3;
int b = 12;
int c = 24;
printf("&a = %p, &b = %p, &c = %p\n", &a, &b, &c);
exchange(&a, &b, &c);
int d = exchange(&a, &b, &c);
printf("int d = %x\n", d);
return 0;
}
And ran it on my computer (gcc 7.3.0 on Ubuntu 18.04), and got this output:
&a = 0x7ffca0126788, &b = 0x7ffca012678c, &c = 0x7ffca0126790
xp = 0x7ffca0126788, yp = 0x7ffca012678c, zp = 0x7ffca0126790
xp = 0x7ffca0126788, yp = 0x7ffca012678c, zp = 0x7ffca0126790
int d = a0126790
It appears that lower 32 bits of the parameter zp is being returned from exchange. But If I move the call to printf to the end of exchange, it always returns 62, which is the value returned from printf itself.
My guess is, when you don't return a value from a function, probably the register used to hold the value to be returned retains the value returned by the subsequent function call. If no more function is called, then somehow it gets the value of a parameter, which I can't explain or guess.
But all these things are specific to the gcc on my computer (maybe yours too). Actually this is undefined behavior and you never know what would happen (quoting one of my professors: "The universe might get destroyed, who knows?").
When I ran the same code on ideone (which is gcc 6.3), I found the returned value to be 0.
I can't tell where is wrong in your program, so I put your code on my IDE, and surprisingly it even can't build. And the warning shows : Control reaches end of non-void function in Line 12 (the end } of the exchange function). so i tried to fix this problem by add a sentence : return z; . And it works!
I think it's because your function exchange is an int value returned function, unlike the void kind, it has to have a return value. so add one to it. it will run very well
int main ()
{
int a, b;
call(&b);
printf("%d, %d",a , b);
}
void call(int *ptr)
{
}
Desired output:
50, 100
How to write the call function so as to modify both the variables to get the desired output??
Not sure where the values 50 and 100 are coming from or exactly what you are asking but maybe this will help with your question.
Since C is pass by value you need to send pointers to actually change the value inside another function.
Since the call function will have pointer values you need to dereference the pointers before changing the value.
Here is an example:
void call(int *a, int *b)
{
*a = 50;
*b = 100;
}
int main()
{
int a, b;
call(&a, &b);
printf("%d, %d\n", a, b);
}
While we are exploring the many ways this output could be achieved, consider that the function could store state in a static variable:
#include <stdio.h>
void call(int *ptr);
int main(void)
{
int a, b;
call(&a);
call(&b);
printf("%d, %d\n",a , b);
}
void call(int *ptr)
{
static int store = 0;
store += 50;
*ptr = store;
}
Program output:
50, 100
Note that you may also be able to do this as follows, without any modifications to main(). But be warned that this method invokes undefined behavior! It is undefined behavior to write to a location past the end of an array object, and in the case of a and b, these are considered to be array objects of size 1. Here we are assuming that this write will work, and that a and b are stored next to each other in memory. We further assume that a has the higher address in memory.
I would say that you should never do this, but I can see no other way to modify a from the function call() without knowing the address of a. You have been warned.
void call(int *ptr)
{
*ptr = 100;
*(ptr + 1) = 50;
}
Try something like this:
void call(int *ptr)
{
*ptr = 100;
}
int main ()
{
int a, b;
a = 50;
call(&b);
printf("%d, %d",a , b);
}
See demo
Maybe you want this:
int main ()
{
int a, b;
call(&a, &b);
printf("%d, %d",a , b);
}
void call(int *ptr1, int *ptr2)
{
*a = 50;
*b = 100;
}
To change a local variable in function a by calling function b you have two options.
1) Let function b return a value that you assign to the variable in function a. Like:
int b() {return 42;}
void a()
{
int x = b();
printf("%d\n", x);
}
This does, however, not seem to be what you are looking for.
2) Pass a pointer to the variable to function b and change the variable through that pointer
void b(int* p) // Notice the * which means the function takes a pointer
// to integer as argument
{
*p = 42; // Notice the * which means that 42 is assigned to the variable
// that p points to
}
void a()
{
int x;
b(&x); // Notice the & which means "address of x" and thereby
// becomes a pointer to the integer x
printf("%d\n", x);
}
int main()
{
int a,b;
call(&b);
printf("%d, %d\n", a,b);
}
int call(int *ptr)
{
int *m;
m = ptr++;
*ptr = 50;
*m = 100;
}
so I'm studying for a final and we are given this block of codeL
#include <stdio.h>
int a;
void addOne(void) {
a++;
printf(“W. a = %d\n”, a);
}
int removeOne(int a) {
int b = a – 1;
printf(“R. b = %d\n”, b);
}
void swap(int a, int *b) {
int temp = a;
a = *b;
*b = temp;
}
int main() {
a = 5;
int b = 20;
if (b > 15) {
int a = 53;
removeOne(b);
addOne(a);
printf(“X. a = %d\n”, a);
}
printf(“Y. a = %d, b = %d\n”, a, b);
swap(a, &b);
printf(“Z. a = %d, b = %d\n”, a, b);
return 0;
}
We are instructed to give the outputs of the program. I'm having trouble with the addone(a) where I came up with 54, the correct answer was 6. Is it 6 because when the function is declared it has the void (don't remember the technical term but the information it takes in to the function) rather than something like int a?
My more direct question is why does the function take the a initialized in the main function rather than the a in the if?
The reason that the answer is 6:
Note at the top that a is declared as a global. Later, in main there is a call to addOne(a) inside of a code block. That code block defines a local variable a as well. The a that is passed in that scope is the local a (53). It is passed into a function that accepts an unnamed void variable. In that function, however, there is a reference to a. Due to scoping, this will be the global a (5), so a++ will result in an output of 6.
That is a horrible exam question.
I'm trying to do the calculation inside a function, but i'm not sure why it's not working:
int calculate(int x){
x = x + 2;
return x;
}
int main(){
int x = 0;
int i;
for(i=0;i<10;i++){
calculate(x);
}
printf("i = %d, x = %d\n", i, x);
}
I understand that x is 0 every time it passes through the function. But how do I fix it?
Supposedly i should return 10, and x should return 20.
You can actually pass the pointer of that integer you want to change, not the value itself. In that case, the new (increased) integer will be stored in the original level of scope (actually at the exact same memory spot), where it was defined, which is in this case is your main function. So your code, should look like this:
void calculate(int *x)
{
*x += 2;
}
int main(void)
{
int x = 0;
for (int i=0; i<10; i++)
{
calculate(&x);
printf("i=%d, x=%d\n", i, x);
}
return 0;
}
OUTPUT:
i=0, x=2
i=1, x=4
i=2, x=6
i=3, x=8
i=4, x=10
i=5, x=12
i=6, x=14
i=7, x=16
i=8, x=18
i=9, x=20
Variables can shadow each other. You don't have to ensure that you never, ever use i anywhere else in fear of messing with the i in your for loop, because a new scope will get a new copy of the same name (like when two different people have the same name).
To fix this, you can return the value from your calculate function. I named it x2 to clearly differentiate it from your original x:
int calculate(int x2){
x2 = x2 + 2;
return x2;
}
int main(){
int x = 0;
int i;
for(i=0;i<10;i++){
x = calculate(x);
}
printf("i = %d, x = %d\n", i, x);
}
If you want x to change, you need to pass it by reference, not by value.
void calculate(int *x){
*x = *x + 2;
}
int main(){
int x = 0;
int i;
for(i=0;i<10;i++){
calculate(&x);
}
printf("i = %d, x = %d\n", i, x);
}
You're passing x by value, so calculate only changes a local copy. When calculate returns, the result is lost. You need to return the modified value from calculate and assign it to something in main.
You're passing in x as a value (ie. it is copied). So x inside the calculate function is not the same as x outside of it. Thus, when you change its value, the change is not reflected in the x that is in main.
The following would be preferable. Note that you need to return a value from the calculate function, and then assign what it returns to some value.
int calculate(int x){
return x + 2; /* CHANGED */
}
int main(){
int x = 0;
int i;
for(i=0;i<10;i++){
x = calculate(x); /* CHANGED */
}
printf("i = %d, x = %d\n", i, x);
}
Change:
for(i=0;i<10;i++){
calculate(x);
}
to:
for(i=0;i<10;i++){
x = calculate(x);
}
Your function returns a value, thus you need to store it somewhere.
In the function you can just change one thing and iguess it will work
Int calculate(int &x)
And keep rest other things same
Basically u can use "alias"