I have a C program
#include<stdio.h>
void f(const int* p)
{
int j;
p = &j;
j = 10;
printf("Inside function *p = %d\n",*p);
*p = 5;
printf("Inside function *p = %d\n",*p);
j = 7;
printf("Inside function *p = %d\n",*p);
}
int main()
{
int i = 20, *q = &i;
f(q);
}
Compilation of the program gives the error
Assignment of the read only location *p
at the line *p = 5;
Why is that the assignment j = 10; is valid and *p = 5; is an error.
const int *p means that you can't modify the integer that p is pointing to using p, as in *p = 5;. The integer it points to may not be a const int, which is why j = 10 works. This prevents coders from modifying integer being pointed to.
const int* p mean you can not change the content in the address of p
which is you can not chanage *p
const int mean , its value remain same until program ends so you can not change its value.
Related
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.
I'm trying to protect the -a- array of the my_sum_array function from the changes. In the function block I do not make any changes to -a-, but I have a warning (warning: assignment to 'int *' from 'const int *' discards the qualifiers [-Wincompatible-pointer-types-discards-qualifiers]). I know I could remove const to make the program work, but I would like to understand if something is missing from me.
#include <stdio.h>
#define MAX 5
int my_sum_array(const int a[], int n);
int main(void) {
int values[5] = {4, 7, 1, 7, 8};
printf("The sum in my_sum_array is :%d\n", my_sum_array(values, MAX));
return 0;
}
int my_sum_array(const int a[], int n) {
int *p, sum = 0;
for (p = a; p < a + n; p++)
sum += *p;
return sum;
}
The warning is caused by the assignment p = a in the for loop. The variable is defined as int *p, a pointer to non-const int. The warning is correct, "assignment to int * from const int * discards the qualifiers". It's as though you've casted away the constness of the a pointer parameter.
I'd change your function to:
int my_sum_array(const int a[], int n) {
int sum = 0;
for (const int *p = a; p < a + n; p++)
sum += *p;
return sum;
}
This defines p as a pointer-to-const, just like a, and also limits its lifetime to the for loop.
Make your p pointer as:
int const * p;
i.e.
here, p is a pointer to a const integer
Change type of p to:
const int *p;
So now you end up with:
const int * p;
int sum = 0;
I have code snippet that I can't understand how it works, because of one line that does a double dereference. The code looks like this:
void afunction(int**x){
*x = malloc(2 * sizeof(int));
**x = 12;
*(*x + 1) = 13;
}
int main(){
int *v = 10;
afunction(&v);
printf("%d %d\n", v[0], v[1]);
return 1;
}
I understand that the first element of the pointer to pointer gets the value 12, but the line after that I just can't seem to understand. Does the second element in the first pointer get value 13?
The code is rather easy to understand if you use a temporary variable, eg:
void afunction(int**x)
{
int* t = *x;
t = malloc(2 * sizeof(int));
*t = 12;
*(t+1) = 13;
}
so:
x is a pointer to a pointer to int
*x yields a int* (pointer to int)
**x = is like *(*x) = so you first obtain the pointer to int then by dereferencing you are able to set the value at the address
The last part *(*x+1) = can be broken down:
int* pointerToIntArray = *x;
int* secondElementInArray = pointerToIntArray + 1;
*secondElementInArray = 13;
The purpose of using a pointer to pointer here is that you can pass the address to an int* to the function and let the function allocate the memory and fill it with data. The same purpose could be done by returning an int*, eg:
int* afunction() {
int* x = malloc(sizeof(int)*2);
*x = 12;
*(x+1) = 13;
return x;
}
int main() {
int* v = afunction();
return 0;
}
I would like to print out the contents a pointer pointing to. Here is my code:
int main(){
int* pt = NULL;
*pt = 100;
printf("%d\n",*pt);
return 0;
}
This gives me a segmentation fault. Why?
These lines:
int* pt = NULL;
*pt = 100;
are dereferencing a NULL pointer (i.e. you try to store value 100 into the memory at address NULL), which results in undefined behavor. Try:
int i = 0;
int *p = &i;
*p = 100;
Because you are trying to write to address NULL.
Try:
int main(){
int val = 0;
int* pt = &val;
*pt = 100;
printf("%d\n",*pt);
return 0;
}