I have a question which involves calling a function with 2 parameters of a pointer to a pointer
int main(void)
{ ...
int *ptrp = &p, *ptrq = &q;
int **ppp = &ptrp, **ppq = &ptrq;
swap_ptr(ppp,ppq);/* &ptrp, &ptrq passed */
/* to swap_ptr() */
return 0;
}
void swap_ptr(int **ptrA,int **ptrB)...
We have to swap the values of ptrp and ptrq, so does that mean in the swap_ptr function I just use *ptrA and *ptrB to swap them or is it some other pointer statement?
Thanks
It's the same concept as swapping anything:
void swap(int* a, int* b)
{
int tmp = *a;
*a = *b;
*b = tmp;
}
In this case, you just happen to be swapping int* instead of int:
void swap(int** a, int** b)
{
int* tmp = *a;
*a = *b;
*b = tmp;
}
Yes, *ptrA would refer to the variable ptrp in main and *ptrA would refer to ptrq. Swap these two values as you would for any other type and ptrp will now point to q and ptrq to p.
Since this sounds like it might be homework I'll let you come up with the three lines of code.
*ptrp refers to the value that the pointer is pointing to.
ptrp refers to the value of the pointer (the memory location)
swap_ptr could simply store one of the values in a tmp var and then swap the values.
I'm kind of new with these algorithms/techniques but I've had came up with this function;
function swap(int *p1, int *p2) {
*p1 = *p1 + *p2;
*p2 = *p1 - *p2;
*p1 = *p1 - *p2;
}
You can test this function like that;
int a = 10;
int b = 20;
printf("%d %d\n", a, b); // 10 20
swap(&a, &b);
printf("%d %d\n", a, b); // 20 10
Here's a 3-step explanation for better understanding;
*p1 = *p1 + *p2;
Add the values coming from p1 (*p1=10) and p2 (*p2=20) and store result on p1 (*p1=30).
*p2 = *p1 - *p2;
We know result of the addition, calculate the old value of p1 by subtracting current value of p2 (current *p2=20) from value coming from p1 (*p1=30) and store result on p2 (calculated *p2=10).
*p1 = *p1 - *p2;
Since the value of p1 (*p1=30) did not change on step 2 and we still have the old value of p1 on p2 (*p2=10), we can divide p2 into p1 and store the result on p1 (calculated *p1=20)
So as you can see we swapped two ints without defining any temporary variable and making pass-by-reference function call.
The reason of pass-by-reference is to minimize usage of memory. Because every pass-by-value call allocates new variables on the memory (to be deleted by GC or not) depends on how much parameter you've passed to the function.
Related
This question already has answers here:
Simple swap function...why doesn't this one swap?
(12 answers)
Closed 5 months ago.
I'm very new to C and just starting to learn pointers. I'm very confused by this piece of code in lecture. I'm wondering if anyone can explain it to help me understand.
#include <stdio.h>
void swap(int *p1, int *p2)
{ int *p;
p = p1; p1 = p2; p2 = p;
}
void main()
{ int a, b;
int *pointer_1, *pointer_2;
scanf("%d, %d", &a, &b);
pointer_1 = &a; pointer_2 = &b;
if (a < b) swap(pointer_1, pointer_2);
printf("\n%d > %d\n", *pointer_1, *pointer_2);
}
The problem is why this doesn't swap a and b?
In your code
p = p1; p1 = p2; p2 = p;
you're swapping the addresses (the change is local to the function scope). You need to swap the values (*p1, *p2) stored in those memory locations.
This function
void swap(int *p1, int *p2)
{ int *p;
p = p1; p1 = p2; p2 = p;
}
actually swaps nothing. The pointers are passed to the function by value
if (a < b) swap(pointer_1, pointer_2);
That is the function deals with its own local variables p1 and p2 that were initialized by copies of values of the original pointers used as argument expressions. Within the function these local variables are indeed swapped but the original pointers used as argument expressions stay unchanged.
You need to swap objects of the type int passed to the function swap by reference that is through pointers to them. That is you need to change values of the variables a and b defined in main.
So the function should look the following way
void swap(int *p1, int *p2)
{ int x;
x = *p1; *p1 = *p2; *p2 = x;
}
Dereferencing the pointers you get a direct access to the pointed variables a and b and can exchange their values.
If you want to exchange values of the pointers pointer_1 and pointer_2 themselves then the function can look the following way
void swap(int **p1, int **p2)
{ int *p;
p = *p1; *p1 = *p2; *p2 = p;
}
and the function will be called like
if (a < b) swap( &pointer_1, &pointer_2);
That is again the arguments must be passed by reference through pointers to them. In this case the values of the variables a and b will not be changed but values of the pointers will be changed.
Try yourself the both approaches and compare their results. Output in main the variables a and b and the values of the dereferenced pointers as for example
printf("a = %d, b = %d\n", a, b );
printf("*pointer_1 = %d, *pointer_2 = %d\n", *pointer_1, *pointer_2);
void swap(int *p1, int *p2)
{
int *p;
p = p1; p1 = p2; p2 = p;
}
Your function, swap, does not actually modify the values of p1 and p2
You can fix it by replacing p = p1; p1 = p2; p2 = p; with this
void swap(int *p1, int *p2)
{
int p;
p = *p1; *p1 = *p2; *p2 = p;
}
In this case, we modify the value of what the pointer is pointing to.
static void swapAddr(int *numOne, int *numTwo)
{
int *tmp;
tmp = numOne;
numOne = numTwo;
numTwo = tmp;
}
int main(void)
{
int a = 15;
int b = 10;
printf("a is: %d\n", a);
printf("Address of a: %p\n", &a);
printf("b is: %d\n", b);
printf("Address of b: %p\n", &b);
swapAddr(&a, &b);
printf("\n");
printf("a is: %d\n", a);
printf("Address of a: %p\n", &a);
printf("b is: %d\n", b);
printf("Address of b: %p\n", &b);
return 0;
}
When I compile and run this piece of code, the output is
a is: 15
Address of a: 0x7fff57f39b98
b is: 10
Address of b: 0x7fff57f39b94
a is: 15
Address of a: 0x7fff57f39b98
b is: 10
Address of b: 0x7fff57f39b94
Clearly the result is not what I intended, since the address does not seem to have been swapped at all.
You generally can't change the address of a variable.
Your 'swapAddr' function changes its parameter values, but these are local to the function - you're not changing anything outside the function. Perhaps the best way of understanding it is that a function parameter always receives a copy of the value that was passed to the function. In this case, you get a copy of the address of a and a copy of the address of b. You can and do change the values of the variables holding those copies (numOne and numTwo), and seeing as they are pointers you could (but don't) change the values that they point at (the values of variables a and b) - but you can't change the addresses of the original variables.
To break it down:
static void swapAddr(int *numOne, int *numTwo)
{
int *tmp;
tmp = numOne;
At this point, tmp and numOne both point to the value of the a variable...
numOne = numTwo;
Now, numOne points instead to the value of the b variable...
numTwo = tmp;
}
And finally, numTwo now points to the value of the a variable. The function returns and numOne and numTwo no longer exist after that point. The addresses of the variables a and b did not change at any stage.
You could however write a function which exchanges the addresses in two pointer variables:
static void swapAddr(int **ptrOne, int **ptrTwo)
{
int *tmp;
tmp = *ptrOne;
*ptrOne = *ptrTwo;
*ptrTwo = tmp;
}
This would allow you to pass the address of two pointer variables, and on return the pointers would be swapped - each one pointing at what the other did previously. But again, this would not change the address of any variable that those pointers happened to point to.
The pointers are passed to the function by value, so changing what they point to isn't going to change the value of the passed parameters in the calling function.
When the function is called, a copy of each pointer is made and saved to the stack. Then the function reads each pointer value off the stack and manipulates them. It never changes the value of the original pointer that was copied onto the stack.
Remember that in C values are passed by value to functions, meaning that the values are copied. When you modify an argument in a function you only modify the local copy inside the function, not the original value that was passed to the function. This goes for pointers as well.
To solve your problem you must pass the arguments by reference, but unfortunately C doesn't have that, it only have pass by value. However, pass by reference can be emulated by passing pointers to the data, just like you do in the function. You must however dereference the pointer to get the values from where the pointers point to, and use those values to do the actual swapping:
int temp = *numOne; // Note: temp is a value not a pointer
*numOne = *numTwo;
*numTwo = temp;
static void swapAddr(int *numOne, int *numTwo)
In this function you are passing 2 pointers by value. This allows you to modify the int pointed to by the pointers but not the pointers themselves.
Use this function definition instead that passes pointers to pointers and allows modifying the pointers themselves
static void swapAddr(int **numOne, int **numTwo) {
int *tmp = *numOne;
numOne = *numTwo;
numTwo = tmp;
}
You could use it like this for example:
int *a = malloc(sizeof(int));
int *b = malloc(sizeof(int));
*a = 15;
*b = 10;
swapAddr(&a, &b);
You canlt change the addresses. The adderss of a is the address of a and that will remain the same until the end of days.
You can do:
static void swapAddr(int **numOne, int **numTwo)
{
int *tmp;
tmp = *numOne;
*numOne = *numTwo;
*numTwo = tmp;
}
int main(void)
{
int a = 15;
int b = 10;
int *pa= &a;
int *pb= &b;
swapAddr(&pa, &pb);
}
What you want to achieve is something like
int *c = &a;
&a = &b;
&b = &a;
This is not possible (you can check: it will not compile). A variable that is created is placed at one place in memory and stays there. So when you create a variable a it will stay variable a and it will not be able to change its identity to that of another variable b.
What you can do is use two pointers int *p1, *p2 to int. These pointers can change their value and point to other objects during lifetime:
p1 = a;
p2 = b;
p1 = b;
p2 = a;
a and b will stay the same, but p1 and p2 can point to different objects over time.
So a thing that would be possible:
static void swapaddr(int **pp1, int **pp2)
{
int *pp;
pp = *pp1;
*pp1 = *pp2;
*pp2 = pp;
}
int main(void)
{
int a = 15, b = 10;
int *pA = &a, *pB = &b;
swapAddr(&pA, &pB);
}
In this example a and b would keep their identity and address, but pA and pB would change their value and pA would point to b and pB would point to pA.
You cannot change the addresses of the variables.however you can change values of pointers,which store addresses as their value,here is an example :
#include <stdio.h>
void swapAddr(int **numOne, int **numTwo)
{
int *tmp;
tmp = *numOne;
*numOne = *numTwo;
*numTwo = tmp;
}
int main(void)
{
int a = 15;
int b = 10;
int *p_a = &a;
int *p_b = &b;
printf("Address of a: %p\n", p_a);
printf("Address of b: %p\n", p_b);
swapAddr(&p_a,&p_b);
printf("\n");
printf("p_a : %p\n",p_a);
printf("p_b : %p\n",p_b);
return 0;
}
I am trying to better understand pointers and referencing in C, and my course provided the following program as an example.
#include <stdio.h>
void swap(int* a, int* b);
int main(void)
{
int x = 1;
int y = 2;
swap(&x, &y);
printf("x is %i\n", x);
printf("y is %i\n", y);
}
void swap(int* a, int* b)
{
int tmp = *a;
*a = *b;
*b = tmp;
}
I shambled together the following to see if it would help me understand better what's happening, mainly in regards to the need to use & versus *(dereference). Basically, the syntax of declaring a pointer to int type (int* a) versus using an asterisk to "dereference" (*a = *b) is quite confusing to me, and I was hoping someone could enlighten me. Here's another version of the above that I thought would help clarify, but really doesn't:
#include <stdio.h>
void swap(int* a, int* b);
int main(void)
{
int x = 1;
int y = 2;
int *a = &x;
int *b = &y;
swap(a, b);
printf("x is %i\n", x);
printf("y is %i\n", y);
}
void swap(int* a, int* b)
{
int tmp = *a;
*a = *b;
*b = tmp;
}
In short, my question is, is there a functional difference between what these two programs are doing? What is the difference between a dereference (*a = *b) versus using the & operator (*a = &x)".
You're confusing declaration and assignment.
*a = *bis called assignment. Notice it does not include a type name.
int *a = &x on the other hand is called declaration. Notice that you initialize the pointer with the address of x. You are not dereferencing the pointer, but are declaring it as a pointer to int.
Look at this:
int main() {
int a = 5;
int b = 2;
int *c = &a; // c when dereferenced equals 5; **Declaration**
int *d = &b; // d when dereferenced equals 2; **Declaration**
int tmp = *c; // tmp equals 5
*c = *d; // c when dereferenced now equals 2 **Assignment**
*d = tmp; // d when dereferenced now equals 5 **Assignment**
return 0;
}
Finally, when you declare and initialize a pointer in the same statement, you assign the pointer the address of what you want to have point at it. When you want to change the value the object points to, you dereference it using *. On the other hand, if you want to change what it points to, you do not dereference it.
&xreturns the address of x. x is of type integer and a is of type pointer to integer. In this case, (*a = &x), you are assigning the address of x to a variable of type "pointer to integer", which is a. (*a = *b) is a assign operation between two variables of the same type which is integer. I said integer because even though a and b are "pointers to integers", in that operation they are dereferenced and therefore the integer value to which these are pointed to is read.
The confusion I think you have is because (*a = &x) only makes sense during a pointer initialization.
If you set *a = *b since a and b are pointer variables, the * operator will retrieve the value of a cell in memory that b points to it and puts it to the cell that a points to it.
For *a = &x, the & operator finds the address of the cell that allocated to the x variable, and puts it in the cell that a points to it.
In short, my question is, is there a functional difference between
what these two programs are doing?
No, the functional effect is exactly the same. In
int *a = &x;
int *b = &y;
swap(a, b);
// swap(&a, &b)
The type of a is the same of &a, namely int* (pointer to int). The only difference is that you're using other variables to store that, which is not really needed logically but it is absolutely fine to have it, especially if it could help you understand the syntax.
What is the difference between a dereference (*a = *b) versus using &
(*a = &x).
*a = *b assigns the value pointed to by b (obtained with *b) in the ones pointed to by a. To see it more clearly,
int tmp = *b;
*a = tmp;
&(*a = &x) is not a valid expression because you can't store an address into an int (actually you can, but that's beyond the point).
In Dennis M Richies book "C programming language" it talks about pointers, and one of the examples is swapping two pointers:
void swap(int *a, int *b)
{
int temp;
temp = *a;
*a = *b;
*b = temp
}
What's confusing me slightly is *a = *b. If b is already a pointer being passed in, why does it need to be dereferenced before assigning it to *a? Why wouldn't a = b work as their both pointers already?
a = b means you are assigning address of b to a which not the right way.
for swapping two numbers means you need to get value at that address and that value you have to swap.
so right way is to do *a = *b; i.e value at the address of b assigned to value at the address of a.
On doing a = b, both a and b will point to location pointed by b, this will defeat the purpose of passing a and b as reference; as the swap() will not be reflected after the function returns.
*ptr is dereferencing of the pointer.
*a = *b; means you are putting in the value contained at location b into the location where a points to. And this is what is required in the swap function.
a = b; means you are assigning value of pointer b to pointer a. This is not what you need in swap logic.
The reason for the confusing is that the function actually does not swap pointers.
Let's at first assume that the function has to swap pointers and its implementation has to be look as you think
void swap(int *a, int *b)
{
int *temp;
temp = a;
a = b;
b = temp
}
The function can be called the following way
int x = 10;
int y = 20;
int *px = &x;
int *py = &y;
swap( px, py );
Parameters of a function are its local variables that are initialized by arguments. So the function call can look the following way
void swap(/*int *a, int *b*/)
{
int *a = px;
int *b = py;
int *temp;
temp = a;
a = b;
b = temp
}
Within the function these local variables were swapped but the original arguments were not changed. Local variables a and b got copies of values stored in px and py. Thus after exiting the function these local variables will be destroyed and at the same time px and py will not be changed.
To change the pointers the function should look the following way
void swap(int **a, int **b)
{
int *temp;
temp = *a;
*a = *b;
*b = temp
}
In this case the function swaps values pointed to by pointers int **a and int **b and these values are values stored in px and py. Of course the function must be called like
swap( &px, &py );
Now let's return to the original function
void swap(int *a, int *b)
{
int temp;
temp = *a;
*a = *b;
*b = temp
}
It is similar to the function that swaps pointers. However in this case it swaps objects pointed to by int *a and int *b.
I am new with pointers and I am trying to create a function that changes value of variable a to variable b, and the value of variable b to variable a.
I think I have everything right except the function. In the function I am trying to make the value of pointer a (*a) and assign it to the value pointer b has, and vice verca. However my output is "a is now y and b is now y".
Is this because when I assign *a to b, b will get *a's value which just changed to an y?
#include <stdio.h>
void change(char* a, char* b)
{
*a = b;
*b = a;
}
int main(void)
{
char a = 'x';
char b = 'y';
printf("a is now %c and b is now %c\n", a, b);
change(&a, &b);
printf("a is now %c and b is now %c\n", a, b);
return 0;
}
Your change function is wrong:
void change(char* a, char* b)
{
char temp = *a;
*a = *b;
*b = temp;
}
First make a temporary variable - copy it in a temp variable, then swap the value. This line is UB:
*a = b;
*b = a;
You are trying to store a pointer's value in a char.
Yes, your first assignment overwrites the value that is needed in the second one.
The solution is to use some temporary storage to hold the one of the variable values during the swap:
void change(char *a, char *b)
{
const char old_a = *a;
*a = *b;
*b = old_a;
}
There is also a trick you can do to go around this (using bitwise XOR), but it's scary so ignore it at this point.