I am trying to understand what happens when I execute this
#include <stdio.h>
const int MAX = 3;
int main () {
//double var[] = {10.0, 100.1, 200.2};
double var[3];
int i;
double *ptr;
double **ptr2;
for(i=0;i<MAX;i++)var[i] = 10.0*(double)(i+1);
/* let us have array address in pointer */
ptr = var;
ptr2 = &ptr;
for ( i = 0; i < MAX; i++) {
printf("Address of var[%d] = %x\n", i, *ptr2 );
printf("Value of var[%d] = %f\n", i, **ptr2 );
/* move to the next location */
ptr2++;
}
return 0;
}
This code snippet gives a seg fault at the second iteration
Address of var[0] = b0e04370
Value of var[0] = 10.000000
Address of var[1] = 0
However this works if instead of calling ptr2 we call ptr
for ( i = 0; i < MAX; i++) {
printf("Address of var[%d] = %x\n", i, ptr );
printf("Value of var[%d] = %f\n", i, *ptr );
/* move to the next location */
ptr++;
}
giving
Address of var[0] = 3e9e89a0
Value of var[0] = 10.000000
Address of var[1] = 3e9e89a8
Value of var[1] = 20.000000
Address of var[2] = 3e9e89b0
Value of var[2] = 30.000000
It segfaults because the next address doesn't really hold anything.
I changed the loop to this and now it works the way you expect it to:
/* let us have array address in pointer */
ptr = var;
ptr2 = &ptr;
for (i = 0; i < MAX; i++)
{
printf("Address of var[%d] = 0x%x\n", i, (void*)*ptr2 );
printf("Value of var[%d] = %f -- using ptr\n", i, *ptr);
printf("Value of var[%d] = %f -- using ptr2\n", i, **ptr2);
ptr++;
// This updates ptr2, which was missed out
ptr2 = &ptr;
}
With this it prints the following:
Address of var[0] = a313c9b0
Value of var[0] = 10.000000 -- using ptr
Value of var[0] = 10.000000 -- using ptr2
Address of var[1] = a313c9b8
Value of var[1] = 20.000000 -- using ptr
Value of var[1] = 20.000000 -- using ptr2
Address of var[2] = a313c9c0
Value of var[2] = 30.000000 -- using ptr
Value of var[2] = 30.000000 -- using ptr2
The reason your code segfaults at second iteration (and not at first) is
ptr = var;
ptr2 = &ptr;
With these two lines, ptr2 not holds the address of ptr while ptr is pointing to var[0]
Lets see the second iteration now with the updated code:
ptr++;
which makes ptr to point to var[1]
ptr2 = &ptr;
which makes ptr2 to hold the address of ptr which now point to var[1].
I guess this explains. May be you could try the third iteration yourself.
Related
//I want to revert array back to original state after 2nd printf statement OR code any other way such that next code a=++(*p) operates on origianl array not on Update array.
CODE:
#include <stdio.h>
#include <stdlib.h>
int main(){
int arr[]={10,20,30,40,50};
int *p = arr;
int a;
printf("\n arr[0] = %d, arr[1] = %d, a = %d, *p = %d", arr[0], arr[1],a , *p);
a= ++*p;
printf("\n arr[0] = %d, arr[1] = %d, a = %d, *p = %d", arr[0], arr[1],a , *p);
//I WANT TO RESET ARRAY BACK TO ORIGINAL STATE after this printf statement or any other way such that next code a= ++(*p) operates on origianl array not on Update array.
a= ++(*p);
printf("\n arr[0] = %d, arr[1] = %d, a = %d, *p = %d", arr[0], arr[1],a , *p);
}
OUTPUT GIVEN:
arr[0] = 10, arr[1] = 20, a = 32767, *p = 10
arr[0] = 11, arr[1] = 20, a = 11, *p = 11
arr[0] = 12, arr[1] = 20, a = 12, *p = 12┌─[user#user]─[~/Documents/vs_code/DS/TEMP]
└──╼ $
OUTPUT EXPECTED:
arr[0] = 10, arr[1] = 20, a = 32767, *p = 10
arr[0] = 11, arr[1] = 20, a = 11, *p = 11
arr[0] = 11, arr[1] = 20, a = 11, *p = 11┌─[user#user]─[~/Documents/vs_code/DS/TEMP]
└──╼ $
Stop writing C code and learn modern C++.
You can use std::array, which has value semantics. This allows you to simply copy the array and copy it back later if that is what you want:
#include <cstdio>
#include <cstdlib>
#include <array>
int main(){
std::array arr{10,20,30,40,50};
int *p = &arr[0];
int a = 0;
printf("\n arr[0] = %d, arr[1] = %d, a = %d, *p = %d", arr[0], arr[1],a , *p);
std::array arr2 = arr;
a= ++*p;
printf("\n arr[0] = %d, arr[1] = %d, a = %d, *p = %d", arr[0], arr[1],a , *p);
//I WANT TO RESET ARRAY BACK TO ORIGINAL STATE after this printf statement or any other way such that next code a= ++(*p) operates on origianl array not on Update array.
arr = arr2;
a= ++(*p);
printf("\n arr[0] = %d, arr[1] = %d, a = %d, *p = %d", arr[0], arr[1],a , *p);
}
Modifying the copy would have been better.
Thanks for logic: #sam-varshavchik
Copy the original array values somewhere else, then copy them back when you're done fiddling with the array.
#include <stdio.h>
#include <stdlib.h>
int main(){
int arr[]={10,20,30,40,50};
int *p = arr;
int a;
int length= sizeof(arr)/sizeof(arr[0]);
int arr2[length];
for(int i=0; i<length;i++){
arr2[i]= arr[i];
}
printf("\n arr[0] = %d, arr[1] = %d, a = %d, *p = %d", arr[0], arr[1],a , *p);
a= ++*p;
printf("\n arr[0] = %d, arr[1] = %d, a = %d, *p = %d", arr[0], arr[1],a , *p);
p= &arr2;
a= ++(*p);
printf("\n arr[0] = %d, arr[1] = %d, a = %d, *p = %d", arr[0], arr[1],a , *p);
}
This question already has answers here:
Why use double indirection? or Why use pointers to pointers?
(18 answers)
Closed 1 year ago.
I know that int *p is a pointer but what does int **p mean exactly? What type of value is that? When I say now p= something, how is that working? I am seeing this in the creation of two-dimensional arrays with pointers.
In short, int **p; is a pointer to a pointer to an int. So, for example:
int i, j; // Integers;
int *p = &i; // Pointer to i
*p = 1; // i is now 1
int *q = &j; // Pointer to j
int **s = &p; // Pointer to p
**s = 2; // i is now 2
s = &q; // s now points to q (pointing to j)
**s = 16; // j is now 16
s = &p; // s now points to p (pointing to i)
**s = 3; // i is now 3
p = &j; // p now points to j
**s = 17; // j is now 17
One use case for a pointer to pointer could be a function which needs to output a pointer to an int and return a success/failure status:
#include <stdbool.h>
bool getIntHandle(unsigned handleId, int **handle)
{
static int handles[] = {12, 23, 34, 45};
bool success = (handleId < sizeof(handles)/sizeof(handles[0])); // Check that handleId is in range
if(success)
{
*handle = &handles[handleId];
}
return success;
}
int main(void)
{
int *handle;
bool success = getIntHandle(2, &handle); // Get a pointer to the integer at index 2
printf("*handle = %d\n", *handle);
return 0;
}
p is a pointer to a pointer to an int. It's the type int **p and the variable p stores an address.
Here is an example of its use. p is an array of two integer pointers. The first of the pointers p[0] points to an array of 3 integers, and the 2nd to an array of 4 integers (combined this is known as ragged array):
#include <stdio.h>
#include <stdlib.h>
int main() {
int **p = malloc(2 * sizeof(int *));
printf("p = %p\n", p);
p[0] = malloc(3 * sizeof(int));
printf("p[0] = %p\n", p[0]);
p[0][0] = 0;
p[0][1] = 1;
p[0][2] = 2;
p[1] = malloc(4 * sizeof(int));
printf("p[1] = %p\n", p[1]);
p[1][0] = 3;
p[1][1] = 4;
p[1][2] = 5;
p[1][3] = 6;
free(p[0]);
free(p[1]);
free(p);
return 0;
}
The most common use, however, is with a regular 2d array that is passed to a function which degrades to a pointer to a pointer.
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.
Trying to understand how a pointer works in a function that returns an array.
When the temp array is returned to the function, why is it that p[0] is 1 and p[1] is 3? Since x and y variable are swapped within the function and temp[0] and temp[1] are not swapped.
int *swap(int *x, int *y){
static int temp[2];
temp[0] = *x;
temp[1] = *y;
*x = temp[1];
*y = temp[0];
return temp;
}
int main() {
int x = 3;
int y = 1;
int *p = swap(&x, &y);
GPIO_PORTF_AHB_DATA_BITS_R[LED_RED] = LED_RED;//turn on red led
delay(p[0]);
GPIO_PORTF_AHB_DATA_BITS_R[LED_RED] = 0;//turn off red led
delay(p[1]);
}
why is it that p[0] is 1 and p[1] is 3
It isn't.
Replacing your microcontroller-specific code with:
printf("p[0] = %d, p[1] = %d\n", p[0], p[1]);
and running your code on a computer gives me the output:
p[0] = 3, p[1] = 1
as expected.
I am studying C and I've been given a task.
"Modify the program by adding a new variable that stores the address of x. Then use your variable to update (indirectly) the value of i and then print out the new value to demonstrate that your modification has worked."
This is the code I have to modify:
#include <stdio.h>
int main()
{
int i, j;
int * p, * q;
int ** x;
i = 100;
j = 200;
p = &i;
q = &j;
x = &p;
*p = *p + *q;
*q = **x / 2;
**x = *p + j;
printf(" i = %d\n", i);
printf("&i = %p\n", &i);
printf(" j = %d\n", j);
printf("&j = %p\n", &j);
printf(" p = %p\n", p);
printf("&p = %p\n", &p);
printf("*p = %d\n", *p);
printf(" q = %p\n", q);
printf("&q = %p\n", &q);
printf("*q = %d\n", *q);
printf(" x = %p\n", x);
printf("&x = %p\n", &x);
printf("*x = %p\n", *x);
printf("**x= %d\n", **x);
return 0;
}
This is what I have attempted. I declared the variable that stores the address. I then assigned it the address of x of x (newVariable) and then tried to create an increment update of address i. Compiling the program gave me the following errors:
ptr3.c:14:18: warning: assignment makes integer from pointer without a cast [-Wint-conversion]
*newVariable = &x; /* Assign new variable address of x */
^
ptr3.c:19:19: error: lvalue required as unary ‘&’ operand
newVariable = &i++; /* Autoincrement address by 1 */
^
ptr3.c:21:12: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘int *’ [-Wformat=]
printf("&newVariable = %d\n", newVariable); /* New printf statement */
^
The code:
#include <stdio.h>
int main()
{
int i, j;
int * p, * q;
int ** x;
int * newVariable; /* New variable of type address*/
i = 100;
j = 200;
p = &i;
q = &j;
x = &p;
newVariable = &x; /* Assign new variable address of x */
*p = *p + *q;
*q = **x / 2;
**x = *p + j;
newVariable = &i++; /* Autoincrement address by 1 */
printf("&newVariable = %d\n", newVariable); /* New printf statement */
printf(" i = %d\n", i);
printf("&i = %p\n", &i);
printf(" j = %d\n", j);
printf("&j = %p\n", &j);
printf(" p = %p\n", p);
printf("&p = %p\n", &p);
printf("*p = %d\n", *p);
printf(" q = %p\n", q);
printf("&q = %p\n", &q);
printf("*q = %d\n", *q);
printf(" x = %p\n", x);
printf("&x = %p\n", &x);
printf("*x = %p\n", *x);
printf("**x= %d\n", **x);
return 0;
}
Version 3:
#include <stdio.h>
int main()
{
int i, j;
int * p, * q;
int ** x;
int * newVariable; /* New variable of type address*/
i = 100;
j = 200;
p = &i;
q = &j;
x = &p;
newVariable = &x; /* Assign new variable address of x */
*p = *p + *q;
*q = **x / 2;
**x = *p + j;
newVariable = &i++; /* Autoincrement address by 1 */
printf("&newVariable = %d\n", newVariable); /* New printf statement */
printf(" i = %d\n", i);
printf("&i = %p\n", &i);
printf(" j = %d\n", j);
printf("&j = %p\n", &j);
printf(" p = %p\n", p);
printf("&p = %p\n", &p);
printf("*p = %d\n", *p);
printf(" q = %p\n", q);
printf("&q = %p\n", &q);
printf("*q = %d\n", *q);
printf(" x = %p\n", x);
printf("&x = %p\n", &x);
printf("*x = %p\n", *x);
printf("**x= %d\n", **x);
return 0;
}
Could someone tell me what I have done wrong? I fail to see what is wrong with the program.
If the new variable will hold the address of x, it needs to be a
pointer to the type of x which is int **. So:
int ***newVariable;
You're assigning the address of x correctly, with:
newVariable = &x;
To modify i, let's think a little. The original x itself points
to something else (in this case p) that points to i. So
the newVariable adds an extra level, meaning you just have to
dereference it three levels to get access to i. If, for example, you
want to modify i by incrementing it you can then do it with:
***newVariable += 3; // increment i (indirectly) by 3
To print the value of i you can use itself directly, or p which
points to it, or x which points to p, or newVariable which
points to x. So these statements will yield the same result:
printf("i = %d\n", i);
printf("i = %d\n", *p);
printf("i = %d\n", **x);
printf("i = %d\n", ***newVariable);
You shouldn't provide two main() functions in one file.
First problem is at newVariable definition:
int ** x; /* pointer to pointer */
/* Since you want to store adress of x, you should declare pointer to pointer to pointer */
int *** newVariable; /* variable to store adress of x */
Second problem is on how do you indirectly increment i value:
/* Since newVariable -> x -> p -> i (where "->" means "is a pointer to") */
(***newVariable)++; /* increment value of i by 1 */
You need to use ***newVar and point to address of x.Then you can change pointed value of newVar and show that x is also changed.
#include <stdio.h>
int main()
{
int i, j;
int * p, * q;
int ** x;
int *** newVar;
i = 100;
j = 200;
p = &i;
q = &j;
x = &p;
newVar = &x;
// prove that newVar is pointing to same as x
printf("**x= %d\n", **x); //100
***newVar = 12345;
printf("***newVar= %d\n", ***newVar); //12345
printf("**x= %d\n", **x); //12345
printf("*p= %d\n", *p); //12345
printf("i= %d\n", i); //12345
//prove that they are all pointing to same address
printf("p= %p\n", p);
printf("*x= %p\n", *x);
printf("**newVar= %p\n", **newVar);
return 0;
}