Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
In the code below in order to swap between px and py you need a pointer to point to the address of py and px to swap them effectively.
My question is with the int temp when the value of px is put into it how does it give the correct value back because there is no pointer pointing to it to be able to give the right value and how is the address of int temp not clone to give a wrong value?
void swap(int px, int py)
{
int temp;
temp = px;
px = py;
py = temp;
}
//pointer version
void swap(int *px, int *py)
{
int temp;
temp = *px;
*px = *py;
*py = temp;
}
Both functions swap the int values. But does that swap affect the calling code's ints?
With the second swap(), the effect of the swap is seen in the original a,b as that function works with the addresses of the original a,b.
int a = 1;
int b = 2;
swap_version2(&a, &b);
printf("%d %d\n", a, b); // prints 2 1
With the first swap(), the effect of the swapped is not seen in the original c,d. as the swap() function was swapping copies of c,d. Net effect: the first swap function simply wastes time. It does not swap c,d.
int c = 3;
int d = 4;
swap_version1(c, d);
printf("%d %d\n", c, d); // prints 3 4
There are two important things you need to know.
1) When calling a function in C, the arguments are always passed by value. If you make changes inside the functions to the variables holding the passed value, the changes will be lost the moment the function returns. In other words - any change made inside the function can't be seen outside the function.
2) When working with pointer the * operator in front of the pointer means the location pointed to by the pointer. It is called dereferencing the pointer. So if you do *px = 5; you do not change any pointer value! You change the value at the location pointed to by the pointer.
A closer look at your code:
In your first example you have something like:
void swap(int px, int py)
{
int temp;
temp = px;
px = py;
py = temp;
}
int main(void)
{
int x = 10;
int y = 100;
swap(x, y);
printf("%d %d\n", x, y);
return 0;
}
In C everything is passed by value. So when you call swap it is the values 10 and 100 which is passed to the function. It is not the variables x and y. In other words - px and py in the function has nothing to do with the variable x and y in main. This means that any change made to the variables px and py is lost when the function returns and x and y does not change.
Your second example is like this:
void swap(int px, int py)
{
int temp;
temp = *px;
*px = *py;
*py = temp;
}
int main(void)
{
int x = 10;
int y = 100;
swap(&x, &y); // Notice the & operator
printf("%d %d\n", x, y);
return 0;
}
As always we have pass by value. But in this case the values that you pass is the values of two pointer to int. More specific you pass the address of x and y.
Like before you can't change the value that is passed to the function (just like the first example) but you can change the value of whatever the pointer is pointing to.
Here you need to know that * in front of the pointer access whatever the pointer is pointing to.
So doing temp = *px will read the value pointed to by px. In this case it is 10 so temp gets the value 10.
Doing *px = *py reads the value py points to (i.e. 100) and place it where px points (i.e. x in main is now 100).
Doing *py = temp reads the value temp holds (i.e. 10) and place it where py points (i.e. y in main is now 10).
So when the function returns, the value of x and y has been swapped.
Notice that the code never uses a pointer to (aka the address of) temp. The variable temp is just used as an ordinary int.
In this function
void swap(int *px, int *py)
{
int temp;
temp = *px;
*px = *py;
*py = temp;
}
there are swapped values pointed to by px and py. The function does not swap the pointers themselves.
To swap the values pointed to by the pointers you need an intermediate memory where temporary to store the value pointed to by px that will be overwritten by the value pointed to by py.
Thus the function uses local variable temp that temporary stores the value *px.
Pay attention to that in this assignment statement
temp = *px;
the variable temp stores the value pointed to by px that is *px that has type int. It is not the pointer px itself that is assigned to temp.
Related
I am trying to understand pass by value and reference and I thought c was a language of pass by reference and tried to implement a swap function, that changes the values of two numbers to have values of each other, but the values don't seem to change at all. so can you please see the ff code and point out what I am doing wrong? in my thought, since we are assigning the pointer variables to have a value of another variable(which points to a certain number) it should have swapped the values but it's not what is happening(i.e. The values don't get swapped) so there must be some thing I am not understanding. would appreciate if you can help
#include <stdio.h>
void swap(int *a, int *b){
int *temp;
temp = a;
a=b;
b=temp;
}
int main()
{
int a = 78;
int b = 98;
int *c=&a;
int *d=&b;
swap(c,d);
//swap(&a,&b)
printf(" a is %d and b is %d \n",*c,*d);
return 0;
}
C is always pass-by-value.
what you're looking for is
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
This way you will be passing the addresses of the integers you want to swap, and the swap function will swap the values written in those address.
I am trying to understand pass by value and reference and I thought c was a language of pass by reference
No, C is a language of pass by value.
C++ has reference parameters. In C++, you could have written something very close to your original, and it would have worked:
void swap(int &a, int &b){
int temp;
temp = a;
a = b;
b = temp;
}
Declarations like `` say that the parameter will be passed by reference. So when you say things like temp = a and a = b, you're actually affecting the caller's variable, as you want to. (The other change I made here is that temp is a plain int.)
But that was C++. In C, there are no reference parameters, and everything [note 1] is passed by value. But you can use pointers to explicitly simulate pass by reference. It looks like this:
void swap(int *a, int *b){
int temp;
temp = *a;
*a = *b;
*b = temp;
}
This is also close to what you originally wrote, with the exception that we are explicitly manipulating *a and *b. If a and b are pointers to variables in the caller, then we write *a and *b to say that we are manipulating what the pointer points to, that is, the variables in the caller.
In this case we must call
swap(&a, &b)
in the caller (as in fact you had in a comment).
[Note 1: Arguably, there is one place in C that does have pass by reference, and that's when you pass an array to a function. See more discussion at this question.]
In C the term pass by reference means passing an object indirectly through a pointer to it. So dereferencing the pointer you have a direct access to the object pointed to by the pointer.
Thus if you want to change values of the variables a and b within the function swap you need to dereference the passed pointers that point to the variables to get the access to them.
void swap(int *a, int *b){
int temp = *a;
*a = *b;
*b = temp;
}
If you want to swap the pointers themselves to make the pointer c to point to the variable b and the pointer d to point to the variable a then again you need to pass them to the function by reference through pointers to them.
In this case the function will look the following way
void swap(int **a, int **b){
int *temp = *a;
*a = *b;
*b = temp;
}
and can be called like
swap( &c, &d );
You are just swapping the local copies of your pointers, not the things the pointer point to, as you forgot to dereference your pointers. Also, your temp value holds a pointer too, which doesn't make sense - it should hold one of the values you are swapping.
Instead of this...
int *temp;
temp = a;
a = b;
b = temp;
...you need this:
int temp;
temp = *a;
*a = *b;
*b = temp;
For better understanding, let's explain this with an analogy.
Suppose your memory is a cabinet full of drawers. Each draw is labelled with some letter (its address), and in the drawers, there are pieces of paper with other numbers or letters written on them (the values stored at each address). In this explanation I use letters as addresses even though in reality, addresses are numbers as well.
Now let's see what happens in your original code. To simplify the explanation, I will inline the function.
This is what we have then:
int a = 78;
int b = 98;
int *c = &a;
int *d = &b;
int *temp = c;
c = d;
d = temp;
And this is what it does:
// Let's put a note with `78` written on it into drawer `A`.
int a = 78;
// Now we have: A="78"
// Let's put a note with `98` written on it into drawer `B`.
int b = 98;
// Now we have: A="78", B="98"
// Let's put a note with `A` written on it into drawer `C`.
int *c = &a;
// Now we have: A="78", B="98", C="A"
// Let's put a note with `B` written on it into drawer `D`.
int *d = &b;
// Now we have: A="78", B="98", C="A", D="B"
// Let's check the note in drawer `C` (which currently says `A`)
// and put a similar note into drawer `T`.
int *temp = c;
// Now we have: A="78", B="98", C="A", D="B", T="A"
// Let's check the note in drawer `D` (which currently says `B`)
// and put a similar note into drawer `C` (discarding what is
// already there).
c = d;
// Now we have: A="78", B="98", C="B", D="B", T="A"
// Let's check the note in drawer `T` (which currently says `A`)
// and put a similar note into drawer `D` (discarding what is
// already there).
d = temp;
// Now we have A="78", B="98", C="B", D="A", T="A"
If you look at the final result, you will see that the contents of the drawers A and B never changed. We just fiddled around a bit with our drawers C, D and T.
Now let's look at the working solution, again inlined for simplicity:
int a = 78;
int b = 98;
int *c = &a;
int *d = &b;
int temp = *c;
*c = *d;
*d = temp;
And see how it works now:
// Let's put a note with `78` written on it into drawer `A`.
int a = 78;
// Now we have: A="78"
// Let's put a note with `98` written on it into drawer `B`.
int b = 98;
// Now we have: A="78", B="98"
// Let's put a note with `A` written on it into drawer `C`.
int *c = &a;
// Now we have: A="78", B="98", C="A"
// Let's put a note with `B` written on it into drawer `D`.
int *d = &b;
// Now we have: A="78", B="98", C="A", D="B"
// ==== SO FAR SO GOOD, NOW LET'S SEE WHAT IS DIFFERENT THIS TIME ===
// Let's check the note in drawer `C` (which currently says `A`).
// Then LOOK INTO ANOTHER DRAWER according to the note we just found
// (which said `A`), look at the note in there (which currently says
// `78`) and put a similar note into drawer `T`.
int temp = *c;
// Now we have: A="78", B="98", C="A", D="B", T="78"
// Let's check the note in drawer `D` (which currently says `B`).
// Then LOOK INTO ANOTHER DRAWER according to the note we just found
// (which said `B`), look at the note in there (which currently says
// `98`) and prepare a similar note.
// Then check the note in drawer `T` (which currently says `A`).
// Then OPEN ANOTHER DRAWER according to the second note we just found
// (which said `A`), and put the copied note that we got before
// (which said `98`) into that drawer.
*c = *d;
// Now we have: A="98", B="98", C="A", D="B", T="78"
// Let's check the note in drawer `T` (which currently says `78`)
// and prepare a similar note.
// Then check the note in drawer `D` (which currently says `B`).
// Then OPEN ANOTHER DRAWER according to the second note we just found
// (which said `B`), and put the copied note that we got before
// (which said `78`) into that drawer.
*d = temp;
// Now we have A="98", B="78", C="A", D="B", T="78"
The difference is that this time we use C and D only to store a "pointer" to A and B, and not directly any numbers, so we always looked into C or D to find another drawer's letter in there and then continue accessing that drawer, so we ended up actually swapping the numbers in A and B as we wanted.
You may say, "why did we even have to use extra drawers C and D then?", and you would be right - but only because this example inlined the function call. If you call a function, you have to pass some "notes" (arguments) to it which it will put in its own drawers (argument variables) - you can't pass whole drawers (i.e. values by reference). So instead of being able to pass the drawers A and B directly, you do the next best thing and pass two notes with A and B written on them - your pointers - which the function will put into its own drawers C and D at that point. The function can then check what's written on these notes to know which actual drawers (with your numbers in them) you wanted the function to operate on.
By the way, C is pass-by-value, not pass-by-reference. C++ can be both because it has a reference type, but C doesn't. All you can do is use pointers, but then you are technically still passing a pointer by value, although logically speaking, you can view the pointer as reference to some value so you could say you are passing that value by reference, even though syntactically you aren't.
For comparison, in C++ you could do this:
// The & here is *not* related to pointers but means
// "pass this argument by reference", essentially
void swap (int &a, int &b) {
int temp = a;
a = b;
b = temp;
}
// ...
int a = 123;
int b = 456;
swap(a, b);
In terms of the analogy above, this would be equivalent to passing the whole drawers A and B to the function so that the function can temporarily put them into its own cabinet and swap the notes inside of them, instead of passing notes with the labels of your own drawers.
C is strictly pass-by-value - formal parameters in the function definition are always separate objects in memory that receive copies of the values from the actual parameters in the function call. To help make this clear I'm going to use different names for the formal and actual parameters:
void swap( int a, int b )
{
int tmp = a;
a = b;
b = tmp;
}
int main( void )
{
int x = 10, y = 20;
printf( "Before swap: x = %d, y = %d\n", x, y );
swap( x, y );
printf( " After swap: x = %d, y = %d\n", x, y );
return 0;
}
a and b are different objects in memory than x and y - when you call swap, the expressions x and y are fully evaluated, and the results of those evaluations (the integer values 10 and 20) are copied to a and b.
Any changes to a or b have no effect on x or y, so the output of the above program will be
Before swap: x = 10, y = 20
After swap: x = 10, y = 20
To fake pass-by-reference semantics, we use pointers:
void swap( int *a, int *b )
{
int tmp = *a;
*a = *b;
*b = tmp;
}
int main( void )
{
int x = 10, y = 20;
printf( "Before swap: x = %d, y = %d\n", x, y );
swap( &x, &y );
printf( " After swap: x = %d, y = %d\n", x, y );
return 0;
}
a and b are still separate objects in memory from x and y, but instead receiving copies of of the values of x and y, they receive the results of the expressions &x and &y, or the addresses of x and y, giving us this set of conditions:
a == &x // int * == int *
b == &y // int * == int *
*a == x // int == int
*b == y // int == int
The expressions *a and *b can kinda-sorta-but-not-really be thought of as aliases for x and y - writing to *a in swap is the same as writing to x in main.
This time, the output would be
Before swap: x = 10, y = 20
After swap: x = 20, y = 10
In the following code:
#include <stdio.h>
void shuffle(int* a, int* b, int c) {
int temp = *a;
*a = *b + c;
c = *b;
*b = temp;
}
int main() {
int x = 10;
int y = 20;
int z = 35;
shuffle(&x,&y,z);
printf("x: %i\n", x);
printf("y: %i\n", y);
printf("z: %i\n", z);
return 0;
}
The value of 'z' remains 35. Why is that so? Shouldn't the value be 20? Since:
c = *b;
When you pass a, b and c as parameters you can notice something, that int c is not passed as a pointer. In C the parameters can be passed two ways.
The first is reference-passed parameter, the parameter is passed as the address of the variable, any change done to the content of that address will persist even out of the function.
The second way is to pass it as a by-value parameter, in that case, you only create a copy of the content of the "passed" variable to another.
Now, int* a is passed as a reference (because it is a pointer), lets say a=0x12341234(address of a) and its value is 10, and one more time, int c (not a pointer) has 0x10101010 as an address with a value of 35.
Then, when our function is called with a as a pointer and c as a normal integer, we can realize that inside the function the address of a stills 0x12341234, however, address of c is now 0x20202020(for example). We have created a copy of c in another place of the memory. Modifying a copied variable does not modify the original variable. This is like:
int original = 20;
int copy = original;//we see that copy is a COPY of original
copy = 321;//Original still being 20
How the mechanisms of variable's scope work (local, static and global)?
I don't understand this output:
void foo1(int *z)
{
z = (int *)malloc(sizeof(int));
*z = 3;
}
void foo2(int *t)
{
*t = 3;
}
void main()
{
int y = 1;
int x = 2;
foo1(&y);
foo2(&x);
printf("%d %d", y, x);
}
output: 1 3
void foo1(int *z)
{
z = (int *)malloc(sizeof(int));
*z = 3;
}
I am not sure why you are using malloc, but *z ends up pointing to the memory address of the memory you just assigned with the malloc. So overriding the original pointer means the change isn't reflected in the original main() method.
A bit more clear:
You have a pointer * z that is pointing to the y from main(). When you use malloc it returns a pointer, so when you assign that to z, it is now pointing to a different block of memory that has nothing to do with the y from main(). You then assign this new block of memory the value of 3. Hence the original y is unchanged.
Starting in main, int y = 1; creates a local object named y and initializes it to 1.
Then int x = 2; creates a local object named x and initializes it to 2.
Then foo1(&y); calls foo1 while passing it the address of y.
In foo1(int *z), the parameter z is effectively an object local to the function foo1. As foo1 starts, z contains the address of y.
Then z = (int *)malloc(sizeof(int)); allocates memory and assigns the address of that memory to z. This changes z, so z no longer contains the address of y.
Then *z = 3; puts 3 in the place where z points, which is now the allocated memory. So the contents of the allocated memory change. y does not change because z no longer points to y, since z = (int *)malloc(sizeof(int)); changed z.
Then foo1 returns and main calls foo2(&x);, which calls foo2 while passing it the address of x.
In foo2(int *t), the parameter t is effectively an object local to the function foo2. As foo2 starts, t contains the address of x.
Then *t = 3; puts 3 in the place where t points. Since t points to x, this changes the contents of x, so now x contains 3.
Then foo2 returns.
Back inside main, printf("%d %d", y, x); prints the contents of y and x. Since y did not change, it is still 1. Since x did change, it is now 3.
when I try to swap these two integers using pointers, I get segmentation fault.
Basically before I swap, x is assigned to 1 and y is assigned to 2. After I swap x is assigned to 2 and y is assigned to 1.
The program takes two integers x and y and is supposedly meant to swap them:
int swap(int x, int y){
int *swapXtoY;
int *swapYtoX;
*swapXtoY = y;
*swapYtoX = x;
}
Function swap is expecting both of its argument as int, but you are passing int *. Compiler should raise a warning about this.
It seems that you have no idea how pointers work in C. Your function is just assigning two ints to local variables. Function should be like:
int swap(int *x, int *y){
int temp;
temp = *x;
*x = *y;
*y = temp;
}
swap method should accept two pointer, instead of two integers.
Try following.
int swap(int* x, int* y){
int temp = *x;
*x = *y;
*y = temp;
}
You must pass variables by address to functions to change their value.That being said,your functions should expect pointers as well.Here is a generic function that can swap variables of any C data type:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void Swap(void *x,void *y,size_t bytes);
int main(void)
{
int x = 3, y = 4;
Swap(&x,&y,sizeof(int));
printf("x now : %d\n",x);
printf("y now : %d\n",y);
return 0;
}
void Swap(void *x,void *y,size_t bytes)
{
void *tmp = malloc(bytes);
memcpy(tmp,x,bytes);
memcpy(x,y,bytes);
memcpy(y,tmp,bytes);
free(tmp);
}
Firstly, your function passes its arguments by value1, which makes it impossible for the function to make any lasting changes to them.
Secondly, the swap idiom consists of:
defining an intermediate variable, temp, which is initializes to one of the two variables, for example x.
assigning the value of the second variable,y to the first (saved in temp) variable x (now temp has value x and x has value y).
finally, assigning temp, to the second variable, y (now x has the value of y and vice versa).
In C code, this would look like:
void swap (int *x, int *y ) {
// dereference x to get its value and assign it to temp
int temp = *x;
// dereference x and assign to it the value of y
*x = *y;
// complete the swap
*y = temp;
}
Then to call the function:
// if the variables are not pointers
swap(&x, &y);
// if variables are passed via pointers
swap(x_ptr, y_ptr);
You might want to check the meaning of the dereference operator * or address-of operator &.
1. By value: it passes a copy of the passed variable, which prevents any change outside the function.
Here is an example of what I mean. This example is without using pointers and the variables do not swap.
void swap(int x, int y);
main()
{
int a = 33, b = 55;
swap (a, b);
printf("a = %d, b = %d\n", a, b);
}
void swap(int x, int y)
{
int temp;
temp = x;
x = y;
y = temp;
}
Now if you use pointers the variables a and b swap. Why is it that it only works with pointers?
C is a pass-by-value language. Always. That means with this:
void swap(int x, int y)
{
int temp = x;
x = y;
y = temp;
}
you're swapping the values of x and y, obtained from the values passed to the function. When you invoke like this:
int main()
{
int a = 33, b = 55;
swap (a, b); // passing values of a and b
printf("a = %d, b = %d\n", a, b);
}
the values of a and b are passed. So this is your problem. The solution is to make the values passed something that can be used to modify the caller's variables. If you want to modify those variables they need to somehow be addressable from the called code. Hmmm...
The mechanism is called "pass by address", and though it sounds fancy in reality it isn't. It is simply a retooling of pass-by-value, but with a different value type. Whereas before we were passing values of type int we will instead pass addresses of the integer variables and declare the formal parameters to be pointers to int instead. Make no mistake. They're still values, but not of the basic int type. Rather the values passed are addresses of int variables. To access the data at those addresses pointers are used in conjunction with the dereference operator (of which there are several kinds, only one shown here):
void swap(int *ptrToX, int *ptrToY)
{
int temp = *ptrToX; // dereference right, store value in temp
*ptrToX = *ptrToY; // dereference both, assigning value from right to left.
*ptrToY = temp; // dereference left, assign temp value
}
and invoked like this:
int main()
{
int a = 33, b = 55;
swap (&a, &b); // passing addresses of a and b
printf("a = %d, b = %d\n", a, b);
}
Note: Often ill-quoted as the exception to pass-by-value is passing an array. Though the phrase "decays to a pointer" is thrown about like confetti on New Years Eve, I abhor that vernacular. The verb itself implies a functional operation where there is, in fact, none.
The language specifies the value of an array used in an expression is the address of its first element. In other words, its "value" is already an address and as such can simply be passed by-value to a function expecting a pointer to the same base type. Because it is an address, the receiving parameter (a pointer, because thats what holds address values) can then be used to modify the array content from the caller. Second only to multiple levels of indirection (pointers to pointers, etc) it is easily the hardest thing for people new to C to wrap their head around, yet it is important you do so.
When you call swap, the value of the variables a and b are passed to it. These values are passed by copy. When you swap those values in swap, you are only swapping local copies of a and b.
When you pass pointers to variables to a function, you are able to modify the values of the variables in the calling function.
That's called pass by value.
You are just passing values of a & b to the swap function. The swap function copies that value into its variables x & y which are different from a & b. Hence in swap you are working on x & y instead of a & b.
On the other hand, when you pass pointers, you are passing the address where a & b are stored. Your x & y point to the same address and hence you are manipulating the content at that address where a & b are stored. Hence, main gets to see the updated values.
This is the best example to define the advantage/use of function call by reference V/s call by value
In the main() function the two variables has the value
int a = 33, b = 55;
so using these variables in the swap(a,b) function, it just passes the values to the function definition where
void swap(int x, int y)
{
int temp;
temp = x;
x = y;
y = temp;
}
they declare again two variables x,y and the values in this variables are swapped. But the variables x and y are only known to function swap() after execution of the swap() function that variables are no longer valid. So nothing happens to the variables a,b in the main function.
So in order to swap variables using function you've to use
swap(&a,&b);
in main() function , and modify function swap()
void swap(int *x, int *y)
{
int temp;
temp = *x;
*x = *y;
*y = temp;
}
Which passes the address of variables a and b , and the pointers are used to swap the variables,It gets swapped effectively. Since pointer points to the address of the variables the value of the variables get changed.
For more google "call by referece and call by value in c"