Why do these swap functions behave differently? - c

#include <stdio.h>
void swap1(int a, int b)
{
int temp = a;
a = b;
b = temp;
}
void swap2(int *a, int *b)
{
int *temp = a;
a = b;
b = temp;
}
void swap3(int *a, int *b)
{
int temp = *a;
*a = *b;
*b = temp;
}
main()
{
int a = 9, b = 4;
printf("%d , %d\n", a, b);
swap1(a, b);
printf("%d , %d\n", a, b);
swap2(&a, &b);
printf("%d , %d\n", a, b);
swap3(&a, &b);
printf("%d , %d\n", a, b);
}

C has value semantics for function parameters. This means the a and b for all your three swap variants are local variables of the respective functions. They are copies of the values you pass as arguments. In other words:
swap1 exchanges values of two local integer variables - no visible effect outside the function
swap2 exchanges values of two local variables, which are pointers in this case, - same, no visible effect
swap3 finally gets it right and exchanges the values pointed to by local pointer variables.

You're swap2 function has no effect.
You are passing in two pointers. Inside the function, the (parameter) variables a and b are local to the function. The swap2 function just swaps the values of these local variables around - having no effect outside the function itself.
As Anon pointed out, swap1 has the same problem - you're just modifying local variables.

swap1 will not work because the function just copied the arguments, not affecting the variables in main.
swap2 will not work either.

swap1() and swap2() have an effect limited to the scope of the function itself: the variables they swap are parameters passed by copy, and any change applied to them does not impact the source variable of your main() that were copied during the function call.
swap3 works as it acts on the values pointed by the parameters, instead of acting on the parameters themselves. It is the only of the three that chage the value located at the memory adress in which your main()'s a and b variables are stored.

Just for fun, exchange values without the use of a temporary variable
x = x ^ y
y = x ^ y
x = x ^ y

Related

Why the value stored in 'z' is 35? Shouldn't it be 20 since in the function 'c=*b' (c is equal to the value pointed by *b)?

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

update actual values using pass by value

I want to know if there is any way to update original values by using pass by value.
Also i want to know if I can return updated address back to main
Here I dont want to use pass by reference to swap original values in main.
#include<stdio.h>
int a = 100;
int f =200;
int *p, * q;
swap(int, int);
main()
{
printf("%d %d\n", a,f);
swap(a, f);
printf("%d %d\n",a ,f); //values remain same here how to change them
}
swap(int a, int f)
{
int t;
p=&a;
q=&f;
t=*p;
*p=*q;
*q= t;
printf("%d %d\n",a ,f);
}
I want to know if there is any way to update original values by using pass by value.
Yes there is, you need to pass a pointer:
void swap(int* a, int* b)
{
int temp = *a;
*a = *b;
*b = temp;
}
And call it like this:
swap(&a, &f);
Note that there's no pass-by-reference in C, that's a C++ feature. In C everything, including pointers, are passed by value.
And pass-by-value means copy in C, so it's impossible to modify what was passed.
Also i want to know if I can return updated address back to main
Yes you can. Just change the function return type to a pointer type and add a return statement with the address of the variable of your choice.

C pointer referencing another pointer in functions

I discovered that if you assign a pointer address to another pointer's address in a FUNCTION it won't change the in value in the main,
however by doing the same thing in main, it will change. So what is the reason of this?
void func(int *a, int *b){
b = a;
}
int main(){
int i= 5, k =6, *a=&i, *b=&k;
printf("%d %d\n",*a,*b); //output 5 6
b = a;
printf("%d %d\n",*a,*b); //output 5 5
a=&i;
b=&k;
func(a,b);
printf("%d %d\n",*a,*b); //output 5 6
printf("%d %d\n",*a,*b); //output 5 6
}
In this function
void func(int *a, int *b){
b = a;
}
parameters a and b are local variables of the function. After exiting the function they will be destroyed. The function deals with copies of arguments. If you want that the function would change the original arguments themselves you have to pass pointers to them. For example
void swap(int **a, int **b){
int *tmp = *a;
*a = *b;
*b = tmp;
}
Your function:
void func(int *a, int *b){
b = a;
}
doesn't do anything, it just takes two values representing memory addresses as parameters and assigns one to the other without any external effect whatsoever. It just writes the value of the one to the other (probably not even that, because the compiler will likely detect this is pointless and eliminate it altogether), it doesn't do anything with the information stored at those addresses. You will need to deference the pointer to read or write to the memory address it holds the value of, but in the present form, the function will not assign the pointer to the other, but the value of i to k.
If you want a function to change a parameter outside of it, you should pass by reference, which in C is just pass by pointer, so you need to pass a pointer to the pointer, not the pointer - which will pass a copy of that pointer - the same value, while passing as pointer to pointer will pass the address of the pointer in memory, not the value it holds.
So it should be:
void func(int **a, int **b){
*b = *a;
}
and func(&a,&b) and you will reproduce what you do in main via b = a.

Why does a swap function only work when using pointers?

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"

C pointers - Point to the same address

#include <stdio.h>
#include <stdlib.h>
void foo(int *a, int *b);
void foo(int *a, int *b) {
*a = 5;
*b = 6;
a = b;
}
int main(void) {
int a, b;
foo(&a, &b);
printf("%d, %d", a, b);
return 0;
}
Why a = b (foo) doesn't work? printf outputs "5, 6"
Thank you.
It does work; it just doesn't do what you think it does.
In foo(), a = b changes the pointer a to point to whatever b points to. It has no effect on anything outside of the function; it only changes the pointers.
If you want to change the value of the int pointed to by a to be the same as the value of the int pointed to by b, you need to use *a = *b, similar to how you do the assignments in the function already.
The call to foo() ends with its local variables pointing to the same addres, the one of stored in b. This change is not reflected in main(), the caller.
I you liked to actually do this and make this change pemanent, then you would have to pass a pointer to a pointer to foo() (so you can change them), instead of their simple values:
void foo(int **a, int **b) {
**a = 5;
**b = 6;
*a = *b;
}
I have just observed that your code is incompatible with that modification, anyway, since you cannot change two normal variables to point to each other. You'd have to also modify main() this way:
int main(void) {
int a, b;
int * ptrA = &a;
int * ptrB = &b;
foo(&ptrA, &ptrB);
printf("%d, %d (%d, %d)", *ptrA, *ptrB, a, b);
return 0;
}
Using a pseudo-memory map,
In main(),
a b
--------------
| 5 | 6 | <- data
--------------
[1000] [1004] <- address
In the function foo(),
a b ( local to foo(), different from the a & b in main() )
----------------
| 1000 | 1004 | <- data
----------------
[2000] [2004] <- address
So, when in foo()'s scope,
*a = 5; // store 5 in int variable a
*b = 6; // store 6 in int variable b
a = b; // copies contents of pointer variable b to a
So the final map in foo()'s scope is:
a b
----------------
| 1004 | 1004 | <- data
----------------
[2000] [2004] <- address
In foo, a and b are separate local variables. Setting them to have the same value has no effect on the previous values - the last line of foo currently does nothing, basically.
Within foo, a is initially a pointer to the same location as a in main, and b is a pointer to the same location as b in main. The last line just makes the value of a in foo the same as b - namely a pointer to the same location as b in main. So if you add a line
*a = 7;
at the end of foo, then you'd see output of "5, 7".
(Your code would definitely be easier to talk about if you used different variable names in main and foo, by the way.)
If you're trying to make a and b within main "aliased" to each other, you're not going to be successful. They're separate local variables on the stack, and will remain so. You can't make the stack "shrink" to alias the two, whatever you do.
I'm not sure what you're going after... if it's to get a and b to contain the same value, try *a = *b.
Because when foo is called, the values of the pointers are copied into the function. If you want to change the values of the pointers themselves, you need to pass a pointer to a pointer into the function.
a and b are local to the function foo (they are on the stack), when program returns from the function data on the stack is lost. when you assign b to a, you are only modifying memory addresses on the stack, not their values.

Resources