Why does a swap function only work when using pointers? - c

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"

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

Simple Function in C pointer vs passed value

I would just like to confirm that when I have a function of the sort
int subtract(int a, int b)
{
return a-b;
}
I am passing values when i call subtract(3,2) rather than pointers.
Thanks,
Yes you are
a parameter of type int a means pass an integer by value to the function
a parameter of type int* a means pass a a pointer to some integer to the function.
so for this
int subtract(int a, int b)
{
// even if I change a or b in here - the caller will never know about it....
return a-b;
}
you call like this:
int result = substract(2, 1); // note passing values
for pointers
int subtract(int *a, int *b)
{
// if I change the contents of where a or b point the - the caller will know about it....
// if I say *a = 99; then x becomes 99 in the caller (*a means the contents of what 'a' points to)
return *a - *b;
}
you call like this:
int x = 2;
int y = 1;
int result = substract(&x, &y); // '&x means the address of x' or 'a pointer to x'
Yes, C always pass function parameters by value . To pass a pointer you have to specify the star (asterisk) that identify the pointer type.
Bear in mind that C always pass by value function parameters even in the case of a pointer, in that case the address of the pointer is actually copied .
Yes, you are passing values. A pointer would be denoted by an asterisk after the type name and before the variable name.

Why do these swap functions behave differently?

#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

Simple swap function...why doesn't this one swap?

I'm new to C and still trying to grasp the concept of pointers. I know how to write a swap function that works...I'm more concerned as to why this particular one doesn't.
void swap(int* a, int* b)
{
int* temp = a;
a = b;
b = temp;
}
int main()
{
int x = 5, y = 10;
int *a = &x, *b = &y;
swap(a, b);
printf(ā€œ%d %d\nā€), *a, *b);
}
You're missing *s in the swap function. Try:
void swap(int* a, int* b)
{
int temp = *a;
*a = *b;
*b = temp;
}
That way, instead of just swapping the pointers, you're swapping the ints that the pointers are pointing to.
Your swap() function does work, after a fashion - it swaps the values of the variables a and b that are local to swap(). Unfortunately, those are distinct from the a and b in main() - so you don't actually see any effect from swapping them.
When thinking about pointers, you need to be clear on a few abstractions.
An object in memory. This can be of any type (and size). An integer object, for example, will occupy 4 bytes in memory (on 32 bit machines). A pointer object will occupy 4 bytes in memory (on 32 bit machines). As should be obvious, the integer object holds integer values; a pointer object holds addresses of other objects.
The C programming language lets symbols (variables) represent these objects in memory. When you declare,
int i;
the symbol (variable) i represents some integer object in memory. More specifically, it represents the value of this object. You can manipulate this value by using i in the program.
&i will give you the address of this object in memory.
A pointer object can hold the address of another object. You declare a pointer object by using the syntax,
int* ptr;
Just like other variables, the pointer variable represents the value of an object, a pointer object. This value just happens to be an address of some other object. You set the value of a pointer object like so,
ptr = &i;
Now, when you say ptr in the program, you are referring to its value, which is the address of i. But if you say *ptr, you are referring to not the value of ptr, but rather the value of the object whose address is in ptr i.e. i.
The problem with your swap function is that you are swapping values of pointers, not the values of objects that these pointers hold addresses for. To get to the values of objects, you would have to use *ptr.
C is a pass-by-value language. Your swap routine doesn't dereference the pointers passed to it, so from main's perspective nothing has happened.
The pointers are passed by value. This means a & b are still a and b when the come back from the function;
try something like this
void swap(int* a, int* b)
{
int temp = *a;
*a = *b;
*b = temp;
}
The right way to do it:
void swap(int* a, int* b)
{
int temp = *a; // Temp is set to the value stored at a (5)
*a = *b; // value stored at a is changed to the value stored at b (10)
*b = temp; // value stored in address b is changed to 5.
}
It does swap. It swaps local pointers a and b inside swap function. It swaps them perfectly fine, as it should.
If you want to swap the values these pointers are pointing to, you should re-implement your swap function accordingly, i.e. make it swap the pointed values, not the pointers.
Umm maybe using this
void swap(int** a, int** b)
{
int** temp = a;
a = b;
b = temp;
}
int main()
{
int x = 5, y = 10;
int *a = &x, *b = &y;
swap(&a, &b);
printf(ā€œ%d %d\nā€), *a, *b);
}
Without using a third variable (temp)
void swap(int* a,int* b)
{
// a = 10, b = 5;
*a = *a + *b; // a now becomes 15
*b = *a - *b; // b becomes 10
*a = *a - *b; // a becomes 5
}
zildjohn1's answer is the easiest and clearest way to do it. However if you insist on swapping the pointers, then you have to pass the pointer to the pointer because the pointer itself is passed by value.
You need to send the address of a and b for swap function so while calling swap function you must call ass swap (&a,&b)
So that you pass the address, and alter the address
#define SWAP(a,b) ((a)=(b)+(a),(b)=(a)-(b),(a)=(a)-(b))
Works good.

Arrays vs Local variables in C Programming

The following code is trying to make a point (probably the difference between arrays and local variables) I only have a vague idea on the code. Would someone please elaborate? Thanks
void doit(int x[10], int y) {
y = 30;
x[0] = 50;
}
void main(void) {
int x[10];
int y = 3;
x[0] = 5;
printf("x[0] is %d and y is %d\n", x[0], y);
doit(x, y);
printf("x[0] is %d and y is %d\n", x[0], y);
}
It is showing that arrays are not really passed directly to functions - instead, the address of the first member of the array is passed.
That means that if the called function modifies the array that was "passed", it is modifying the original array in the caller.
On the other hand, when the called function modifies the plain int parameter y, it is modifying a local copy of the variable, and the change is not reflected in the caller.
In C, all arguments are passed by value. However, arrays decay into a pointer to the first element to the array when they get passed; the result is effectively as if the array was passed by reference.
In your code, the doit() function can mutate the array pointed to by x, but it cannot mutate the simple int value in y.
y is passed by value meaning that a temporary copy is created, you have to pass it as a pointer to modify it:
void doit(int x[10], int* y) {
*y = 30;
x[0] = 50;
}
Declaring an array is also not really needed. The compiler anyway understands only that it is a pointer and does (usually) not check the boundaries.
void doit(int* x, int* y) {
*y = 30;
x[0] = 50;
}
Local variables are passed as value where as in arrays the reference is passed not the actual values. so when you change the value in child array the parent array will get changed. Arrays are same as pointers in using the reference

Resources