Function changes pointer arguments, but calling side can't see change - c

i want to understand the nature of pointers work. And have a simple example of swap function. First is working as expected, the second fails.
I can't understand the second function swap2(). I'm swapping the addresses successfully but after the function exit the values stay the same...
Why?
void swap1(int *x, int *y);
void swap2(int *x, int *y);
void startSwapExample() {
int a = 10;
int b = 20;
printf("a = %i, b = %i\n", a, b);
swap1(&a,&b);
printf("a = %i, b = %i\n", a, b);
printf("\n================\n");
int c = 10;
int d = 20;
printf("c = %i, d = %i\n", c, d);
swap2(&c,&d);
printf("c = %i, d = %i\n", c, d);
}
void swap1(int *x, int *y) {
printf("x = %i, y = %i\n", *x, *y);
int temp = * x;
* x = * y;
* y = temp;
printf("x = %i, y = %i\n", *x, *y);
}
void swap2(int *x, int *y) {
printf("x = %i, y = %i\n", *x, *y);
int * temp = x;
x = y;
y = temp;
printf("x = %i, y = %i\n", *x, *y);
}
The output of the program:
a = 10, b = 20
x = 10, y = 20
x = 20, y = 10
a = 20, b = 10
================
c = 10, d = 20
x = 10, y = 20
x = 20, y = 10
c = 10, d = 20
Process finished with exit code 0

In swap2, you are swapping the pointer x and y, both of which only lives within the scope of the swap2 function.
When the function returns, pointer x and y no longer exist and whatever operation you did on the pointer (as opposed to the value pointed by the pointer) has no effect.

swap2() function is not working according to your expectation, reason is below.
void swap2(int *x, int *y) {
printf("x = %i, y = %i\n", *x, *y);
int * temp = x;
x = y;// x holding y
y = temp;// y holding x but not in main() function, only in swap2()
printf("x = %i, y = %i\n", *x, *y); // here you are getting expected output but not in main() function
}
in swap2() function it's swapping but modification is not affecting in main() function because temp as well as x & y are local pointers & and you are not de-referencing anything , so in main() it will be same.

Related

Swap function that works for any types in C

I don't know if it's possible but I'm trying to do a swap function that swaps two variables and works for any type of variable as long as the two variables to swap are of the same type, what I did is using void * type:
#include <limits.h>
#include <stdio.h>
void ft_swap(void **a, void **b)
{
void *tmp;
tmp = *a;
*a = *b;
*b = tmp;
}
int main(void)
{
int a = 5;
int b = INT_MAX;
unsigned long c = 10;
unsigned long d = ULONG_MAX;
printf("BEFORE\na = %d\nb = %d\nc = %zu\nd = %zu\n", a, b, c, d);
ft_swap((void **)&a, (void **)&b);
ft_swap((void **)&c, (void **)&d);
printf("AFTER\na = %d\nb = %d\nc = %zu\nd = %zu\n", a, b, c, d);
return (0);
}
The output is:
BEFORE
a = 5
b = 2147483647
c = 10
d = 18446744073709551615
AFTER
a = 0
b = 5
c = 18446744073709551615
d = 10
I know that void * type is the same size as unsigned long, but can someone explain my what's wrong with the int variables, for me it should work as int is a smaller type? the 5 got swapped, but INT_MAX became 0, what happened here?
EDIT: I did a version as you told me: using long long pointer but it also doesn't work, it changes the value of the int.
Your swap function makes no sense at all (I can't even guess what is the idea behind it).
Your function has to know references to the objects and their size. Then it needs to copy the memory occupied by them.
Here you have the more correct one:
void swap(void *d1, void *d2, size_t size)
{
unsigned char temp[size];
memcpy(temp, d1, size);
memcpy(d1, d2, size);
memcpy(d2, temp, size);
}
struct st
{
int a;
double b;
char c[10];
};
int main(void)
{
int a = 5;
int b = INT_MAX;
unsigned long c = 10;
unsigned long d = ULONG_MAX;
struct st x = {1,2.0, "text1"};
struct st y = {5,20.0, "text2"};
printf("BEFORE\na = %d\nb = %d\nc = %zu\nd = %zu\n", a, b, c, d);
swap(&a, &b, sizeof(a));
swap(&c, &d, sizeof(c));
printf("AFTER\na = %d\nb = %d\nc = %zu\nd = %zu\n", a, b, c, d);
printf("struct before: %d %f %s, %d %f %s\n", x.a, x.b, x.c, y.a, y.b, y.c);
swap(&x, &y, sizeof(x));
printf("struct after: %d %f %s, %d %f %s\n", x.a, x.b, x.c, y.a, y.b, y.c);
return (0);
}
https://godbolt.org/z/er95YYjca

How to visualize the pointers in the code snippet?

I am finding it difficult to visualize this piece of code. I cannot seem to find the ans to this.
I did get the ans for
printf("**r = %d\n",**r);
printf("**s = %d\n",**s);
but other variables are not matching the ans. Please help.
int f(int ** r, int ** s) {
int temp = ** r;
int temp2 = **s;
int * z = *r;
*r = *s;
*s = z;
printf("**r = %d\n",**r);
printf("**s = %d\n",**s);
*z += 3;
**s -= 8;
**r -= 19;
return temp + temp2;
}
int main(void) {
int a = 80;
int b = 12;
int * p = &a;
int * q = &b;
int x = f(&p, &q);
printf("x = %d\n", x);
printf("*p = %d\n", *p);
printf("*q = %d\n", *q);
printf("a = %d\n", a);
printf("b = %d\n", b);
return EXIT_SUCCESS;
}
Expected output:
**r = 12
**s=80
x=92
*p=-7
*q=75
a=75
b=-7
In this declaration the pointers p and q are passed by reference to the function f.
int x = f(&p, &q);
The pointer p points to the variable a and the pointer q points to the variable b.
int a = 80;
int b = 12;
int * p = &a;
int * q = &b;
Within the function f declared like
int f(int ** r, int ** s);
the pointer r points to the pointer p and the pointer s points to the pointer q.
Correspondingly in these declarations
int temp = ** r;
int temp2 = **s;
the variable temp is initialized by the value of variable a and the variable temp2 is initialized by the value of the variable b.
You van imaging these declaration like
int temp = a;
int temp2 = b;
In this code snippet
int * z = *r;
*r = *s;
*s = z;
there are in fact swapped the the pointers p and q pointed to by the pointers r and s. That is after this code snippet the pointer r now points to the pointer q and the pointer s points to the pointer p.
You can imaging this like
*r = q;
*s = p;
The intermediate variable z
int * z = *r;
gets the value of the pointer p.
You can imaging this like
int * z = p;
This statement
*s = z;
did not change the value pointed to by s because before this statement the variable s already pointed to p due to preceding swapping the pointed values of the pointer r and the pointer s.
So these calls of printf
printf("**r = %d\n",**r);
printf("**s = %d\n",**s);
correspondingly will output the value of b and the value of a.
That is the output will be
**r = 12
**s = 80
As the pointer z has the value of the pointer p then after this statement
*z += 3;
the variable a will be increased by 3 and becomes equal to 83.
In these statements
**s -= 8;
**r -= 19;
the variable a will be decrease by 8 and becomes equal to 75 And the variable b is decreased by 19 and becomes equal to -7.
At last the function returns the sum of the initial values of the variables a and b
return temp + temp2;
that is 92.
In these statements in main
printf("x = %d\n", x);
printf("*p = %d\n", *p);
printf("*q = %d\n", *q);
printf("a = %d\n", a);
printf("b = %d\n", b);
there is outputted the value returned by the function f
printf("x = %d\n", x);
that is 92.
As the pointers p and q were swapped in the function then now the pointer p points to b and the pointer q points to a.
printf("*p = %d\n", *p);
printf("*q = %d\n", *q);
So these statements output
*p = -7
*q = 75
And these statements
printf("a = %d\n", a);
printf("b = %d\n", b);
outputs the new values of a and b themselves that is
a = 75
b = -7
As for this statements
printf("**r = %d\n",**r);
printf("**s = %d\n",**s);
then for example the expression *r points to the pointer p. So dereferencing the pointer p like *p that is the same as *( *r ) you will get the lvalue of the variable a.

How can I fix the swapBack function to get the result I intended?

I am trying to implement a swap back function that will swap the values back to the original position. This is the instruction I have to do accordingly:
Implement a second swapping
function, swapBack(int v[2]), that takes the vector v = [x, y] as an input and swaps its entries. Includes
the new function into the program above to swap back the values of x and y.
#include <stdio.h>
void swap(int *pX, int * pY){
int temp = *pX;
*pX = *pY;
*pY = temp;
}
void swapBack(int x, int y){
swap(&x,&y);
}
int main() {
int x = 10;
int y = 5;
swap(&x, &y);
printf("x = %d, y = %d\n", x, y);
swapBack(&x, &y);
printf("x = %d, y = %d\n", x, y);
return x + y;
}
However, both printf produce the same results and I am not sure how to fix it? thanks
You're defining swapBack wrong. It's supposed to take an array (which decays to a pointer) of two integers.
This should be about what you want:
void swapBack(int v[2])
{
int temp = v[0];
v[0] = v[1];
v[1] = temp;
}
A program to test this:
#include <stdio.h>
void swapBack(int v[2])
{
int temp = v[0];
v[0] = v[1];
v[1] = temp;
}
int main(void)
{
int v[2] = {10, 5};
printf("v[0] = %d, v[1] = %d\n", v[0], v[1]);
swapBack(v);
printf("v[0] = %d, v[1] = %d\n", v[0], v[1]);
printf("v[0] + v[1] = %d\n", v[0] + v[1]);
return 0;
}

Pointers and interchange with C

I have a general idea of how to do this, as you can see by the code I did below. The only problem I am having is finishing the interchange part. Basically, what I am trying to do is move the value of the lowest variable into the 1st variable, the second middle value to the 2nd variable, and the biggest to the 3rd variable.
I know I do this with the interchange and using temp somehow, but how would I complete that, because with three values temp would get overridden somehow. What am I missing? So basically a = 4.0, b = 7.0, c = 1.0, c (1.0) needs to go into a, a (4.0) needs to go into b, and b (7.0) needs to go into c.
Thanks!
#include <stdio.h>
void interchange(double * x, double * y, double * z);
int main(void)
{
double a = 4.0, b = 7.0, c = 1.0;
printf_s("Originally a = %d, b = %d, and c = %d.\n", a, b, c);
interchange(&a, &b, &c);
printf_s("Now, a = %d, b = %d, and c = %d.\n", a, b, c);
return 0;
}
void interchange(double * x, double * y, double * z)
{
double temp;
temp = *z;
*y = *z;
* = temp
// what am I missing here? I cant get my head around this above ^^^
}
Thanks for the guidance!
Something like:
void swap(double* first, double* last){
double temp = *first;
*first = *last;
*last = temp;
}
void interchange(double * x, double * y, double * z){
if(*x > *y) swap(x, y);
if(*y > *z) swap(y, z);
if(*x > *y) swap(x, y);
}
the simplest way is:
if (*x > *y) {
temp = *x; // store value of x
*x = *y; // overwrite x with y
*y = temp; // overwrite y with x (which is in temp)
}
// now we sure that x <= y
if (*y > *z) {
temp = *z;
*z = *y;
*y = temp;
}
// now we sure that x <= z and y <= z, but we don't know x/y relationships
if (*x > *y) {
temp = *x;
*x = *y;
*y = temp;
}
// now x <= y <= z

segmentation fault (core dumped) in recursive algorithm

This is a program to calculate a definite integral using numerical quadrature method (I don't know if this is the right translation):
#include <math.h>
#include <stdio.h>
float f(float x){
float y;
y = 4/(+x*x);
return y;
}
void quadra(float a, float b, float *Q, float *E, float f(float)){
float q1, q2, m, h, fa, fb;
h = b - a;
fa = f(a);
fb = f(b);
q1 = (fa+fb)*h/2.;
m = (a+b)/2.;
q2 = ( (fa+2*f(m)+fb) ) *h/4;
*Q = q2;
*E = fabs(q2-q1)/3;
}
void scambia(float *x, float *y) {
float z;
z = *x;
*x = *y;
*y = z;
return;
}
void sort(float x[], int n) {
int flag=1, k=n-1, i;
while (flag == 1 && k > 0) {
flag = 0;
for (i=0; i<k; i++) {
if (x[i]>x[i+1]) {
scambia(&x[i], &x[i+1]);
flag = 1;
}
}
k = k-1;
}
return;
}
int intautri(float A, float B, float TOL, int MAXFUN, float *Q, float *E, int *N, float FUN(float)){
void sort(float [], int);
void quadra(float, float, float*, float*, float(float));
float Q1,Q2,c,d,Iold,Eold,E0,E1,E2,alist[100],blist[100],qlist[100],elist[100];
int n, flag;
quadra(A, B, &Q1, &E0,FUN);
*N = 3;
n = 1;
alist[n] = A;
blist[n] = B;
qlist[n] = Q1;
elist[n] = E0;
*Q = Q1;
*E = E0;
if (*E<=TOL || *N>=MAXFUN){
flag = 1;
}else{
c = alist[n];
d = blist[n];
Iold = qlist[n];
Eold = elist[n];
n = n-1;
quadra(c, (c+d)/2, &Q1, &E1, FUN);
quadra((c+d)/2, d, &Q2, &E2, FUN);
*Q = *Q - Iold + Q1 + Q2;
*E = *E - Eold + E1 + E2;
*N = *N + 6;
intautri(A , B, TOL, MAXFUN, Q, E, N, FUN);
alist[n+1] = c;
blist[n+1] = (c+d)/2;
qlist[n+1] = Q1;
elist[n+1] = E1;
alist[n+2] = (c+d)/2;
blist[n+2] = d;
qlist[n+2] = Q2;
elist[n+2] = E2;
n = n+2;
sort(alist, n);
sort(blist, n);
sort(qlist, n);
sort(elist, n);
flag = 0;
}
;
return flag;
}
int main(){
int intautri(float, float, float, int, float *, float *, int*, float(float));
float TOL, MAXFUN, A, B,Q,E;
int N, J;
float f(float);
A = 0;
B = 1;
TOL = 0.0001;
MAXFUN = 200;
J = intautri(A, B, TOL, MAXFUN, &Q, &E, &N, f);
printf("%d\n", J);
printf("%d\n", N);
printf("%f\n", Q);
return 0;
}
Anyway I compile without problems that code, but when I run it "segmentation fault (core dumped)" appears on terminal. I know that error could depend by memory allocation but I don't understand what is wrong...can you help me??
You have an exit condition in intautri:
if (*E<=TOL || *N>=MAXFUN){
but in the beginning of the function you also have:
*N = 3;
This means that your second exit condition will never fire. Without attempting to understand the logic of the code, I believe that you should:
Initialize N in main().
Remove the *N = 3 assignment in intautri().

Resources