Pointer to pointer as argument in a function - c

I have the following code:
void change_adrs(int **q)
{
int * otheraddess;
*q = otheraddress;
}
I can't understand this assignment: *q = otheraddress;
Could anybody help me to explain this. Why can't we use another assignment, such as:
**q = otheraddress;
*q = *otheraddress;
q = &otheraddress;

void change_ptr(int **q)
{
*q = malloc(somemem);
}
void foo()
{
int *ptr;
change_ptr(&ptr);
}
in this example it will change the value of the ptr itself. When you pass a single star pointer you can only change the referenced object.

Look at the assignment of *q = otheraddress; the same as you look at the following:
int x = 4;
int y = x;
you take 2 vairables of the same type and make an assignment between both of them.
In your case, you use the address of int vairables.
int *otheraddress; is a vairable who can get an address (& operator) to int vairable such as:
int x = 4;
int *p = &x; //p<=the address of x
and int **q; can get an address of a vairable which can get int address. such as you 3rd assignment (which should work fine):
int x = 4;
int *p = &x;//p<=the address of x
int **q = &p;//q<=the address of p
for the other assignmets:
**q = otheraddress; you try to assign int* into int**
*q = *otheraddress; you try to assign int into int *

After declaring the variables, * dereferences them.
For example after declaring something like int **a;, when using it we have:
**a value in value in location stored in a(which is ultimately an int)
*a value in location stored in a (which is another location)
a location stored in a
&a location of a itself
Lets take a look and see why each of your examples don't work:
**q = otheraddress; assigning a location to an int ×
*q = *otheraddress; assigning an int to a location ×
Edit: Lets take a look at these two examples:
q = &otheraddress; assigning a location to a location ✓
*q = otheraddress; assigning a location to a location ✓
Lets look at it this way:
Suppose we have:
int *a;
int **q;
in order to prevent segmentation faults in the future, lets first assign some address to a:
int t = 5
a = &t;
Lets look at the addresses afterq = &a:
//first snippet
0x7fffc3a2b338 // &a
0x5596853c98c0 // a
5 // *a
0x7fffc3a2b340 // &q
0x7fffc3a2b338 // q
0x5596853c98c0 // *q
5 // **q
As expected, &a is put into q, and a holds &t, so **(&a) and **(q) will both hold a value of 5.
Now lets look at the addresses after*q = a:
//second snippet
0x7fffc3a2b338 // &a
0x5596853c98c0 // a
5 // *a
0x7fffc3a2b340 // &q
0x7fffc3a2b345 // q
0x5596853c98c0 // *q
5 // **q
Here, a is put into *q, and a itself is &t, so *(a) and *(*q) with both hold a value of 5.
To understand the difference, we look at an example:
int b = 3;
a = &b;
Using this after the first snippet, a is given another address, and q was declared &a(which hasn't changed), therefore **(q) has the same value as **(&a), which is now 3.
This is just like saying:
int a = 3;
int *b = &a;
a = 5; //even though a has changed, b retains its old value of &a, thus *(b) == *(&a) == 5
However on the second snippet, *q was already declared as a before it had changed, so even though a now has a new address, the address inside *q still hasn't changed. Thus trying to access *(*q) will use the old address and give us 5 again.
This is just like saying:
int a = 3;
int b = a;
a = 5; //even though a has changed, b still retains it's old value of 3

Related

Assigning address of pointer to pointer-to-pointer

I am trying to make a simple piece of c code using pointers work but memory is being overwritten unexpectedly.
I want to create an array of pointers to integers then create a pointer to an integer and assign it's address to an array.
Therefore, the array will point to a pointer to an integer. I did this in a function called add_value_to_array().
Here is my code :
void add_value_to_array(int *** array, int * value) {
*array = &value;
}
int main() {
int ** arr = { 0 };
int value = 5;
int * value_ptr = &value;
add_value_to_array(&arr, value_ptr);
//arr = &value_ptr;
printf("looool\n");
printf("looool\n");
printf("looool\n");
printf("looool\n");
printf("%p\n", arr[0]);
}
What I want is :
arr -> value_ptr -> 5
(arr = &value_ptr
*array = value_ptr
value_ptr = &value
*value_ptr = 5
**arr = 5)
however, this is what I have right after add_value_to_array() is called, but memory is overwritten when I call the printfs(), I get garbage values in my arr variable.
Even weirder, if I do directly arr = &value_ptr instead of calling add_value_to_array, things go as expected and memory is not overwritten by the printfs().
So it seems that memory is allocated differently if I use a function or if I do I do things outside of it.
What is happening that I am seeing this behavior?
Following assumption: You want to create an array of length 1 (maybe greater length later) of pointers to int. And you want that single pointer in the array to point to the local variable named 'value'.
Then:
int* arr[] = { 0 }; // or { NULL }, if you prefer
// ^ creates an array; either you specify size explicitly or it will be deduced
// from initializer, as in this case
Arrays automatically decay to pointer to first element, if you pass them to a function. So:
add_value_to_array(arr, &value);
// ^ decays to pointer
// ^ here you still need a pointer; you can create it directly, though
Little problem left: arr decaying to pointer is of type int**. You need the same type in your function:
void add_value_to_array(int** array, int* value)
// ^ one asterisk less
{
*array
// ^ this one is NOW correct: array points to the first element of arr
// dereferencing gives you exactly this element, i. e. the pointer
= /* & */value;
// ^ must be dropped: you already have a pointer and you assign it to
// another one, which is fine.
}
Be aware that pointers simply are addresses of variables somewhere in memory. A bit simplified:
int n = 10;
int* p0 = &n;
int* p1 = &n; // p1 and p0 point both to the same variable n
int* p2 = p0; // now again p2 points to n
*p0 = 12; // change the value pointed to
printf("%d\n", *p2); // will print 12, as both pointers point to the same address.
Function parameters do not differ in this respect, they are just ordinary variables. And it doesn't play a role if the pointee is a data value or a pointer itself:
int n = 10;
int m = 12;
int* p = &n;
int** p1 = &p; // pointer to pointer to int
int** p2 = p1; // both p1 and p2 point to p
*p1 = &m; // re-assign the POINTER
printf("%d\n", **p2); // again prints 12:
// p1 and p2 both point to p which was reset to m, though...
Thank you all for your answers, this helped me find the bug :
I had to pass my value_ptr by address and not by value.
Here is my corrected code :
void add_value_to_array(int *** array, int ** value_ptr) {
*array = value_ptr;
}
int main() {
int ** arr = { 0 };
int value = 5;
int * value_ptr = &value;
add_value_to_array(&arr, &value_ptr);
//arr = &value_ptr;
printf("looool\n");
printf("looool\n");
printf("looool\n");
printf("looool\n");
printf("%p\n", arr[0]);
}
Thank you all for your help !

Why can't I swap memory address of two variables using a function? C

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;
}

Understanding pointers with a swap program in C

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).

C function with pointers work on one computer, and doesn't work on another

#include <stdio.h>
void swap (int *a, int *b)
{
int *tmp;
*tmp = *a;
*a = *b;
*b = *tmp;
}
int main ()
{
int x = 5;
int y = 7;
swap (&x,&y);
printf ("\n x = %d \n y = %d \n",x,y);
}
I'm using codeblocks, and this code won't work, and I don't understand why... On one computer it works perfectly but on the other it won't run at all.
Any help?
Thanks in advance.
int tmp;
tmp = *a;
*a = *b;
*b = tmp;
What you need is a variable tmp to store the value and not a pointer *tmp.
The below code really a poor way of doing this but
int *tmp = malloc(sizeof(int));
*tmp = *a;
*a = *b;
*b = *tmp;
Once done please free the memory using
free(tmp);
Gopi already corrected your code - adding on to the previous answer - i think this is good to know information for a newbie:
Section 4.1 states:
An lvalue (3.10) of a
non-function, non-array type T can be
converted to an rvalue. If T is an
incomplete type, a program that
necessitates this conversion is
ill-formed. If the object to which the
lvalue refers is not an object of type
T and is not an object of a type
derived from T, or if the object is
uninitialized, a program that
necessitates this conversion has
undefined behavior. If T is a
non-class type, the type of the rvalue
is the cv-unqualified version of T.
Otherwise, the type of the rvalue is
T.
When you try to dereference and uninitialized pointer the behavior is undefined. Undefined means anything can happen - there is no guarantee. So you can get different behavior in different environments.
From Wiki Making pointers safer
A pointer which does not have any address assigned to it is called a wild pointer. Any attempt to use such uninitialized pointers can cause unexpected behavior, either because the initial value is not a valid address, or because using it may damage other parts of the program. The result is often a segmentation fault, storage violation or wild branch (if used as a function pointer or branch address).
What you did here:
int *tmp;
*tmp = *a;
is that you created a pointer to int which is not pointing to anything - basically it contains some junk value (could be your pincode even - who knows).
Your mistake was to use uninitialized memory. Always allocate memory to a pointer before using it. Next, don't forget to free the allocated memory after you're done with it.
Also, you should add return 0; at the end of your main() function.
If you don't mind a second opinion, check the below code.
#include <stdio.h>
#include <stdlib.h>
void swap (int *a, int *b)
{
int *tmp = malloc(sizeof(*tmp));
*tmp = *a;
*a = *b;
*b = *tmp;
free(tmp);
}
int main ()
{
int x = 5;
int y = 7;
swap (&x,&y);
printf ("\n x = %d \n y = %d \n",x,y);
return 0;
}
If you want to use pointers, although it does not make any sense at all
void swap(int *a, int *b)
{
int tmp[1];
*tmp = *a;
*a = *b;
*b = *tmp;
}
here tmp is not strictly a pointer, but you can use the * indirection operator on it.
Or
void swap(int *a, int *b)
{
int value = *a;
int *tmp = &value;
*tmp = *a;
*a = *b;
*b = *tmp;
}
Or you can use malloc as Gopi already pointed out.
If you want to use pointers, then do use pointers:
#include <stdio.h>
void swap (int ** ppx, int ** ppy)
{
int * p = *ppx;
*ppx = *ppy;
*ppy = p;
}
int main (void)
{
int x = 5;
int y = 7;
int * px = &x;
int * py = &y;
printf ("\nx = %d\ny = %d\n", *px, *py);
swap (&px, &py);
printf ("\nx = %d\ny = %d\n", *px, *py);
return 0;
}
Result:
x = 5
y = 7
x = 7
y = 5

Casting pointer & its address to integer pointer

What is the difference between the following two assignments?
int main()
{
int a=10;
int* p= &a;
int* q = (int*)p; <-------------------------
int* r = (int*)&p; <-------------------------
}
I am very much confused about the behavior of the two declarations.
When should i use one over the other?
int* q = (int*)p;
Is correct, albeit too verbose. int* q = p is sufficient. Both q and p are int pointers.
int* r = (int*)&p;
Is incorrect (logically, although it might compile), since &p is an int** but r is a int*. I can't think of a situation where you'd want this.
#include <stdio.h>
int main()
{
int a = 10; /* a has been initialized with value 10*/
int * p = &a; /* a address has been given to variable p which is a integer type pointer
* which means, p will be pointing to the value on address of a*/
int * q = p ; /*q is a pointer to an integer, q which is having the value contained by p, * q--> p --> &a; these will be *(pointer) to value of a which is 10;
int * r = (int*) &p;/* this is correct because r keeping address of p,
* which means p value will be pointer by r but if u want
* to reference a, its not so correct.
* int ** r = &p;
* r-->(&p)--->*(&p)-->**(&p)
*/
return 0;
}
int main()
{
int a=10;
int* p= &a;
int* q = p; /* q and p both point to a */
int* r = (int*)&p; /* this is not correct: */
int **r = &p; /* this is correct, r points to p, p points to a */
*r = 0; /* now r still points to p, but p points to NULL, a is still 10 */
}
Types matter.
The expression p has type int * (pointer to int), so the expression &p has type int ** (pointer to pointer to int). These are different, incompatible types; you cannot assign a value of type int ** to a variable of type int * without an explicit cast.
The proper thing to do would be to write
int *q = p;
int **r = &p;
You should never use an explicit cast in an assignment unless you know why you need to convert the value to a different type.

Resources