why can't I pass in variables to implement a swap function? - c

I just started learning C and I was confused about why do I have to use pointers to implement a swap function?
Version where swap does not work:
#include <stdio.h>
void swap(int i, int j) {
int t = i;
i = j;
j = t;
}
int main() {
int a = 23, b = 47;
printf("Before. a: %d, b: %d\n", a, b);
swap(a,b);
printf("After. a: %d, b: %d\n", a, b);
return 0;
}
Version where swap works:
#include <stdio.h>
void swap(int *i, int *j) {
int t = *i;
*i = *j;
*j = t;
}
void main() {
int a = 23, b = 47;
printf("Before. a: %d, b: %d\n", a, b);
swap(&a, &b);
printf("After . a: %d, b: %d\n", a, b);
}

By default function arguments are passed by value in C and C++. This basically means a copy of the passed argument is received in the function. This copy is distinct from the passed variable and any change on this copy is not reflected back to the passed argument.
So your first snippet actually swaps copies of the passed arguments and not the arguments themselves.
For the swapping to be reflected back to the arguments being passed, You need to pass by reference, In C this is acheived by using pointers. Where the address of the arguments is passed to function and the function actually operates on the memory address passed to it, i.e: the original variable who's value is being passed.

swap(a,b);
void swap(int i, int j) {
int t = i;
i = j;
j = t;
}
The above code fails because, the variables i and j are local to the function swap , which means the variables have their scope limited to the function swap , and their life is lost once the function terminates.
One workaround is to use pass by address as shown in the code below...
swap(&a,&b);
void swap(int* i, int* j) {
int t = *i;
i* = *j;
j* = t;
}
Now the variables i and j, are pointers to original variables a and b , which means they are acting on behalf of a and b, and hence even if the pointers have limited scope within the function, they are able to indirectly modify variables a and b.

Why have you presented two programs back to back?Those are two separate programs.The first one ,despite all its fallacies about void main() and stuff, intends to(but doesn't,as it deals with local variables) swap values by using a function that is passed copies of the integer variables a and b.This is pass-by-value.In fact, C only has pass-by-value, despite what your book by Yeshwant Kanetkar says.Anyways, to make the first program work,use the printf() to display the swapped values inside swap() function itself,as being local variables the change in values won't show in main().
void swap(int i, int j) {
int t = i;
i = j;
j = t;
printf("After. a:%d,b:%d",i,j);
}
The second program, which he may claim uses pass-by-reference, is essentially pass-by-value where copies of the addresses of the variables are passed,not the actual addresses themselves.And again, despite it's non-portable eccentricities like void main(), it does swap the values of a and b.
void swap(int *i, int *j) {
int t = *i;
*i = *j;
*j = t;
}
Output Before. a:23 b:47
After. a:47 b:23
I ran it on CodeBlocks.But then your author Mr.Void Main must have suggested you to use 16-bit Turbo C eh?

You can not do swap this way:
void swap(int i, int j) {
int t = i;
i = j;
j = t;
}
because i and j are passed by value. That means that it is the same as local variable tmp. Thus, modifying of the i and j does not actually modify variables that you passed, as local copies of the i and j do not exist outside the function swap().
Because of it, if you need to modify i and j from main(), you have to pass to swap() addresses of i and j of the main().
That's why the following version is actually works.
void swap(int *i, int *j) {
int t = *i;
*i = *j;
*j = t;
}
EDIT: In order to understand these things better, I would like to recommend you Stanford Lectures Programming Paradigms, that are available at YouTube.

Related

Pointer Confusion: swap method in c

#include<stdio.h>
void swap(int *a,int *b){
int p=*b;
*b=*a;
*a=p;
/*int *p=b;
b=a;
a=p;
*/
}
int main(){
int a,b;
scanf("%d %d",&a,&b);
swap(&a,&b);
printf("%d %d",a,b);
}
Above is the code.
If I put 3 5 as an input, then it should swap its values, and 5 3 should come out as an output.
I got my answer by trying int p=*b thing
However I also tried commented part, but it didn't work.
So, I checked their address in swap and in main.
In swap int *a and int *b their address changed
However, when I came back to main, a and b 's addresses were not changed...
So first I thought: is it not changed in main because parameter int *a,int *b is local variable?
But I also learned that when pointers and arguments are used as arguments their value can change unlike other variables...
I really wonder why the second method(commented part) is not swapping the values...
If you want to change in a function original objects you have to pass them to the function by reference.
In C passing objects by reference means passing them indirectly through pointers that point to the original object.
Otherwise if you will pass the original objects themselves to the function the function will deal with copies of the objects. It is evident that changing copies does not influence on the original objects.
It is exactly what happens in this function
void swap(int *a,int *b){
int *p=b;
b=a;
a=p;
}
The function deals with copies of pointers passed to the function as argument in this call
swap(&a,&b);
That is the function indeed swapped values of the two pointers that are declared as its parameters. But they are not the original pointers passed to the function. They are copies of the pointers. So the values of the original pointers were not changed
The function swap in general can look the following way
void swap( T *a, T *b )
{
T tmp = *a;
*a = *b;
*b = tmp;
}
where T is same type specifier.
So if you want to swap objects of the type int then in the above function T will be int and the function will look like
void swap( int *a, int *b )
{
int tmp = *a;
*a = *b;
*b = tmp;
}
If you want to swap values of pointers of the type int * then T will be int * and the function will look like
void swap( int **a, int **b )
{
int *tmp = *a;
*a = *b;
*b = tmp;
}
Here is a demonstrative program.
#include <stdio.h>
void swap1( int *pa, int *pb )
{
int tmp = *pa;
*pa = *pb;
*pb = tmp;
}
void swap2( int **ppa, int **ppb )
{
int *tmp = *ppa;
*ppa = *ppb;
*ppb = tmp;
}
int main(void)
{
int a = 3, b = 5;
swap1( &a, &b );
printf( "a = %d b = %d\n", a, b );
// reset again the values of the variables
a = 3; b = 5;
int *pa = &a, *pb = &b;
swap2( &pa, &pb );
printf( "*pa = %d *pb = %d\n", *pa, *pb );
return 0;
}
Its output is
a = 5 b = 3
*pa = 5 *pb = 3
That is at first in the program two objects of the type int are swapped, So the imagined type specifier T is int.
Then two pointers that point to the objects a and b are swapped. So the imagined type specifier T int *.
After swapping the pointers the pointer pa now points to the object b and the pointer pb now points to the object a.
In the second method, you use the local variable that is limited in the scope of the function swap. So, the variable a or b in main function is different with variable a or b that is defined as the argument in the swap function.
When you use the pointer, the swap function will change the value that is pointed by the pointer (it means that the function change the value at the address of a and b that are declared in the main function).
Assuming you meant
void swap(int *a,int *b){
int *p=b;
b=a;
a=p;
}
That code just swaps the value of the pointers in the swap() function. That won't swap the addresses around in main() because, as you said, "parameter int *a,int *b is local variable".
When you call the function swap() like this
swap(&a,&b);
the addresses of a and b are passed and become local variables in the swap() function. You can't change the address of a or b - they have a location in memory.
In the code that works
void swap(int *a,int *b){
int p=*b;
*b=*a;
*a=p;
}
you don't change the value of the pointers, you change the values in the memory the pointers point to, which is why that works.
While C is pass-by-value, if you pass the address of something as the value a function can modify something outside its scope because you told the function where that variable is.
In C, all variables declared in a function are local to that specific function.
So, you wrote something in function swap
int *p=b;
What above code will do is, it will copy the value of b into p. So, when the function swap return, it's local variables p, b and a will vanished.

What is the reason for the occurence of a segmentation fault in this case, when I assign pointer in a function

This is the code here:
#include<stdio.h>
void assign (int *a1, int *a2) {
a1 = a2;
}
int main() {
int *a; int b; int *c; int d;
b = d = 5;
a = &b;
printf("%d", *a);
assign(c, &d);
printf("\n%d", *c);
return 0;
}
It's fine when I assign pointers manually in the main() function, but the segmentation fault appears when I assign it in the function. Why is this so?
The function assign has no effect. All it's doing is performing a local assignment which has no effect on the caller. As a result, c is undefined in main and you get a segmentation fault.
In order for assign to do what you intend, you have to pass it the address of c, then do a pointer assignment in assign.
Try the following:
#include <stdio.h>
void assign (int **a1, int *a2) {
*a1 = a2;
}
int main() {
int *a; int b; int *c; int d;
b = d = 5;
a = &b;
printf("%d\n", *a);
assign(&c, &d);
printf("%d\n", *c);
return 0;
}
The output is:
5
5
I also moved the newlines to the end of the format strings, which is the normal place to put them.
c is passed by value into the function assign. This means that modifying a1 from the function will not affect c.
To get the expected results, pass c by reference, i.e, pass the address of c:
assign(&c, &d);
and make slight modifications to the function:
void assign (int **a1, int *a2) {
*a1 = a2;
}
and you are good to go! :-)
Arguments are passed by value in C, so modyfying a1 in assign() won't affect c in main().
c remains uninitialized and it has automatic storage duration, so its value is indeterminate.
Then, you used this inderminate value in printf("\n%d", *c);.
This invokes undefined behavor and the program just happened to cause segmentation fault.

C - swapping two 2D arrays by switching pointers

I would like to swap two variables containing 2D arrays. I believe this can be simply done by swapping their pointers. I tried this code, but it does not work and I have no idea why, perhaps I am not understanding pointers correctly.
#include <stdio.h>
void swap(int ***a, int ***b) {
int ** temp = *a;
*a = *b;
*b = temp;
}
int main(void) {
int a[10][10];
int b[10][10];
a[1][5] = 4;
b[1][5] = 2;
printf("%d, %d\n", a[1][5], b[1][5]);
swap(&b, &a);
printf("%d, %d\n", a[1][5], b[1][5]);
return 0;
}
This outputs
4, 2
4, 2
I would expect it to output
4, 2
2, 4
So, what am I doing wrong?
a and b in main function are not pointers but arrays.
If you want to use pointers, use pointers.
#include <stdio.h>
#define N 10
void swap(int (**a)[N][N], int (**b)[N][N]) {
int (*temp)[N][N] = *a;
*a = *b;
*b = temp;
}
int main(void) {
int a[N][N];
int b[N][N];
int (*pa)[N][N] = &a;
int (*pb)[N][N] = &b;
(*pa)[1][5] = 4;
(*pb)[1][5] = 2;
printf("%d, %d\n", (*pa)[1][5], (*pb)[1][5]);
swap(&pb, &pa);
printf("%d, %d\n", (*pa)[1][5], (*pb)[1][5]);
return 0;
}
This would not work because what you are swapping is actually what the variables in the swap() function are pointing to, and not what they are pointing at. Its like if a was pointing at 5 and b was pointing at 6 in the swap() function, then it will make a point at 6 and b point at 5, without changing the contents of the memory. This would mean the in the main() function they would be residing at the same place and would be getting pointed by the same variable a and b (different from the variable in swap())
To swap you need to swap the contents of that memory in the swap() function, so that it is reflected in the main() function.
Recall that while doing swapping using pointers, one sends the address and actually swaps the content by dereferencing (*p and *q).

Swapping variables with a function doesn't affect the call site

A few lessons ago I learned about variables, and got a question in my homework about swapping two numbers - I used a third variable to solve this question.
The solution looked somewhat like this:
#include <stdio.h>
int main(void) {
int x, y;
scanf("%d %d", &x, &y);
// swappring the values
int temp = x;
x = y;
y = temp;
printf("X is now %d and Y is now %d", x, y);
}
Now I'm learning about functions, and I wanted to try and solve the previous question with a helper swap function.
This is the code I've written:
#include <stdio.h>
void swap(int x, int y) {
int temp = x;
x = y;
y = temp;
}
int main(void) {
int a = 3, b = 4;
swap(a, b);
printf("%d %d\n", a, b);
}
I don't know why, but the output is still 3 4 even though I changed the value inside the swap() function.
Why is this happening?
Pass address of x and y as arguments to function. Right now they are local variables, changes are not made to original variables .
Do as follows-
void swap(int *x,int *y){
/* dereference pointers and swap */
int temp = *x;
*x = *y;
*y = temp;
}
And call in main like this -
swap(&x,&y);
What you are doing is passing parameter by value. It means that during the function call, copies of parameters are created. So inside the function you are working on copies of actual variables.
Instead you need to pass it as a reference. Please read more about pass-by-value vs pass-by-reference.
#include <stdio.h>
void swap(int& x,int& y) //Instead of passing by value just pass by reference
{
int temp=x;
x=y;
t=yemp;
}
int main() {
int a=3,b=4;
swap(a,b);
printf("%d %d\n",a,b);
return 0;
}
EDIT:
C does not have references. Above code will work in c++ instead. To make in work in C, just use pointers and de-reference it inside the function.

C: Having an issue with scope

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.

Resources