I am a newbie trying to understand the working of double pointers and to print double pointers. I increment m by one but it's always pointing to the last value pointed by p. Can someone please help me?
#include <stdio.h>
int main () {
/* an array with 5 elements */
double balance[5] = {1000.0, 2.0, 3.4, 17.0, 50.0};
double *p;
double **m;
int i;
p = balance;
m = &p;
/* output each array element's value */
printf( "Array values using pointer\n");
for ( i = 0; i < 5; i++ ) {
printf("*(p + %d) : %f\n", i, *(p+i) );
}
for ( i = 0; i < 5; i++ ) {
printf("**(m + %d) : %f\n", i, *m);
m++;
}
printf( "Array values using balance as address\n");
for ( i = 0; i < 5; i++ ) {
printf("*(balance + %d) : %f\n", i, *(balance + i) );
}
return 0;
}
Your array balance is like this
+--------+--------+--------+--------+--------+
| 1000.0 | 2.0 | 3.4 | 17.0 | 50.0 |
+--------+--------+--------+--------+--------+
After you initialize p and m it is like this:
+---+
| m |
+---+
|
v
+---+
| p |
+---+
|
V
+--------+--------+--------+--------+--------+
| 1000.0 | 2.0 | 3.4 | 17.0 | 50.0 |
+--------+--------+--------+--------+--------+
That is, m points to the location of p, and p points to the first value of the balance array.
When you dereference m (i.e. when you do *m) you get the value of where m is pointing. This value is another pointer (p) that you need to dereference to get to an element in the array.
Using m the second element in balance (i.e. balance[1]) is (*m)[1].
Now if you increment m (with e.g. m++) it will point to the next element of p:
+---+
| m |
+---+
|
v
+---+
| p |
+---+
|
V
+--------+--------+--------+--------+--------+
| 1000.0 | 2.0 | 3.4 | 17.0 | 50.0 |
+--------+--------+--------+--------+--------+
You can clearly see the problem here: It no longer points to p and you can no longer us it to access the balance array. Dereferencing m after the increment will lead to undefined behavior.
Also, for any pointer or array, the array-indexing expression and the pointer arithmetic expression are equal. So for balance, the expression balance[i] is equal to *(balance + i). There is really no difference between them.
So after you execute
double balance[5] = {1000.0, 2.0, 3.4, 17.0, 50.0};
double *p;
double **m;
p = balance;
m = &p;
the following are all true:
m == &p // double **
*m == p == &balance[0] // double *
**m == *p == balance[0] // double
(*m)[i] == p[i] == balance[i] // double
Remember that the expression a[i] is defined as *(a + i); given the address a, offset i elements (not bytes1) from that address and dereference the result.
This means that *p is equivalent to *(p + 0), which is equivalent to p[0]. Thus, you can use p[i] in place of balance[i]. Since *m == p, you can also use (*m)[i] in place of p[i]. The parentheses are necessary - unary * has lower precedence than postfix [], so *m[i] would be parsed as *(m[i]), which is not what you want here.
You can increment p directly to "walk" through the balance array:
p = balance; // p == &balance[0];
for ( i = 0; i < 5; i++ )
printf( "%f\n", *p++ );
Each time through the loop, p is incremented to point to the next element of balance.
You can do something similar with the expression (*m):
p = balance; // p == &balance[0]
m = &p;
for ( i = 0; i < 5; i++ )
printf( "%f\n", (*m)++ );
Again, the parentheses around *m are necessary; since postfix ++ has higher precedence than unary *, the expression *m++ would be parsed as *(m++), which is not what we want. We don't want to change the value of m, we want to change the value of what m points to, which in this case is p.
Now, suppose we leave p out of the picture completely; can we do something like:
double balance[5] = { ... };
double **m;
*m = balance;
No. In this example, m is an invalid pointer; it hasn't been initialized to point anywhere meaningful, so *m will invoke undefined behavior (which can include, but is not limited to, a segfault). m has to point to an object of type double * before you can dereference it. There has to be a middleman like p in order for that scheme to work.
Pointer arithmetic always takes the size of the pointed-to type into account - if a points to an object of type T, then a + 1 yields the address of the next object of type T, which may be more than 1 byte away from the current address.
Related
#include "stdio.h"
int main()
{
int *pI, *values[2];
int i1[] = {1, 2}, i2[][2] = {{5, 10}, {20, 30}};
// SOME LINES ARE EDITED, AFTER READING COMMENTS
*values = i2[*i1]; // i2[1] = 20 // values[0] = &i2[1][0];
values[1] = i1; // values[1] = 1
pI = &i2[0][0]; //pI = 5
printf(" %d %d\n", **values, *&values[1][1]); //...
// (Edited) expectation: **values = 20 *&values[1][1] = 2
// Result: **values = 20 *&values[1][1] = 2
*pI += pI[i1[1]]; // pI[0] += pI[2] = 5 + 20 = 25
*values = pI; // values points to the 25 (pI)
*(i1 + 1) *= *(values[1] + 1); // i1[1]=2 // i1[1] *= i1[1] = 2*2
printf(" %d %d\n", **values, *&values[1][1]);
// (Edited) expectation: **values = 25 *&values = 4
// Result: **values = 25 *&values = 4
return 0;
}
As you can see my understanding of this code is not the yellow from the egg.
But I would like to understand the steps, that i can solve it by myself the next time
The expression *values is the same as values[0] due to the definition of the subscript operator.
Thus this statement
*values = i2[*i1];
may be rewritten the following way
values[0] = i2[i1[0]];
As i1[0] yields the value 1 then
values[0] = i2[1];
The expression i2[1] yields the second element of the array i2 that is the one-dimensional array of the type int[2] with values {20, 30}.
Array designators used in expression with rare exceptions are converted to pointers to their first elements. So you may write
values[0] = &i2[1][0];
Thus the value of the expression **values is equal to 20.
Again in this statement
values[1] = i1;
the array designator i1 is converted to pointer to its first element. That is you may write
values[1] = &i1[0];
In this expression *&values[1][1] the pair of operators *& in fact does not have an effect. You may write values[1][1]. So this expression yields the second element of the array i1 that is equal to 2.
The variable pI
pI = &i2[0][0];
points to the element &i2[0][0]. This record may be interpreted as
pI = ( int * )i2;
This statement
*pI += pI[i1[1]];
may be rewritten like
*pI += pI[2];
The value of pI[2] is 20 (the third element of the type int of the array i2.
SP you have
*pI += 20;
As a result the element i2[0][0] will contain 25.
This statement
*values = pI;
is equivalent to
values[0] = pI;
So now the pointer values[0] points to the element i2[0][0] that is to the value 25 that is outputted using the expression **values.
This expression statement
*(i1 + 1) *= *(values[1] + 1);
may be rewritten like
i1[1] *= *( values[1] + 1 );
Due to the statement above
values[1] = i1;
values[1] points to the first element of the array i1. So the expression values[1] + 1 points to the second element of the array i1 that is equal to 2.
So you have
i1[1] *= 2;
As a result i1[1] is equal to 4.
This value is outputted by the expression *&values[1][1] that as it was mentioned above is equivalent to values[1][1]
To understand the pointer arithmetic and the implicit conversion of array designators to pointers to their first elements there is no need to write such an obfuscated code.
I am tracing a code but I don't understand how the values are being calculated. My question is on the comments beside the code.
I am tracing code and I understand all the parts except 2. I posted those 2 part below. I will be really glad if someone could help me.
#include <stdio.h>
int function1(int *m, int n)
{
*m = *m + n;
return(*m);
}
int function2(int n, int *m)
{
n = *m + 2;
return(n);
}
int main()
{
int x = 1, y = 3;
int *xptr = &x,*yptr = &y;
x = 1; y = 3;
y = function1(xptr,x);
printf("x = %d, Y = %d\n",x,y);//x=2 but why? shouldn't it be x=1? y=2
x = 1; y = 3;
x = function1(yptr,function2(2,yptr));
printf("x = %d, y = %d\n",x,y);//x=8 y=8 but why? shouldn't y=3?
return 0;
}
So, inside function1:
int function1(int *m, int n) {
*m = *m + n;
return(*m);
} /*
... */
y = function1(xptr,x);
n holds a copy of the value of x,
m holds a copy of the value of xptr, which is the address of x.
*m refers to the contents of the address held by m
...*m = *m + n
That's 'assign to the contents of the address of x: the contents of the address of x, plus the value of x'.
The contents of the address of x (aka it's value) is 1. So we assign 1 + 1 to the contents of address holding the value of x.
In the first printf, x == 2 because when calling function1 the first time *m is a pointer to x, so you assign to the location pointed by m (that is the location of x), *m + n == x + x == 1 + 1 == 2.
In the second printf, y == 8 because in function2 you return its value incremented by 2 (so 3 + 2 == 5) but without updating y, so in function1 you sum the resulting value of function2 to the old value of y (3 + 5 == 8). function1 return also that value, so also x == 8.
I need to pass Two Dimension array to a function as a single pointer. There are different types of approaches are there but due to some constraints(CodeGeneration), I want to pass a single pointer only. I have macros which contain the size of each dimension. I implemented the following way but I am not sure it will work fine for N dimensions also
#define size_1D 3
#define size_2D 3
void fun(int *arr)
{
int i,total_size = size_1D* size_2D;
for(i = 0; i < total_size ; i++)
{
int value = arr[i];
}
}
int main()
{
int arr[size_1D][size_2D] = {{1,2,7},{8,4,9}};
fun(&arr[0][0]);
}
Any loophole is there if I followed the above approach?
void fun(int (*arr)[3]);
or exactly equivalent, but maybe more readable:
void fun(int arr[][3]);
arr is a pointer to two dimensional array with 3 rows and 3 columns. arr decayed to a pointer has the type of a pointer to an array of 3 elements. You need to pass a pointer to an array of 3 elements. You can access the data normally, using arr[a][b].
#define size_1D 3
#define size_2D 3
void fun(int arr[][3])
{
for(int i = 0; i < size_1D ; i++) {
for(int j = 0; j < size_2D ; j++) {
int value = arr[i][j];
}
}
}
int main()
{
int arr[size_1D][size_2D] = {{1,2,7},{8,4,9}};
fun(arr);
}
You can specify the sizes as arguments and use a variable length array declaration inside function parameter list. The compiler will do some job for you.
#include <stdlib.h>
void fun(size_t xmax, size_t ymax, int arr[xmax][ymax]);
// is equivalent to
void fun(size_t xmax, size_t ymax, int arr[][ymax]);
// is equivalent to
void fun(size_t xmax, size_t ymax, int (*arr)[ymax]);
void fun(size_t xmax, size_t ymax, int arr[xmax][ymax])
{
for(int i = 0; i < xmax ; i++) {
for(int j = 0; j < ymax ; j++) {
int value = arr[i][j];
}
}
}
int main()
{
int arr[3][4] = {{1,2,7},{8,4,9}};
fun(3, 4, arr);
}
#edit
We know that the result of array subscript operator is exactly identical to pointer dereference operator of the sum:
a[b] <=> *(a + b)
From pointer arithmetic we know that:
type *pnt;
int a;
pnt + a = (typeof(pnt))(void*)((uintptr_t)(void*)pnt + a * sizeof(*pnt))
pnt + a = (int*)(void*)((uintptr_t)(void*)pnt + a * sizeof(type))
And that the array is equal to the value to the pointer to the first element of an array:
type pnt[A];
assert((uintptr_t)pnt == (uintptr_t)&pnt[0]);
assert((uintptr_t)pnt == (uintptr_t)&*(pnt + 0));
assert((uintptr_t)pnt == (uintptr_t)&*pnt);
So:
int arr[A][B];
then:
arr[x][y]
is equivalent to (ignore warnings, kind-of pseudocode):
*(*(arr + x) + y)
*( *(int[A][B])( (uintptr_t)arr + x * sizeof(int[B]) ) + y )
// ---- x * sizeof(int[B]) = x * B * sizeof(int)
*( *(int[A][B])( (uintptr_t)arr + x * B * sizeof(int) ) + y )
// ---- C11 6.5.2.1p3
*( (int[B])( (uintptr_t)arr + x * B * sizeof(int) ) + y )
*(int[B])( (uintptr_t)( (uintptr_t)arr + x * B * sizeof(int) ) + y * sizeof(int) )
// ---- *(int[B])( ... ) = (int)dereference( ... ) = *(int*)( ... )
// ---- loose braces - conversion from size_t to uintptr_t should be safe
*(int*)( (uintptr_t)arr + x * B * sizeof(int) + y * sizeof(int) )
*(int*)( (uintptr_t)arr + ( x * B + y ) * sizeof(int) )
*(int*)( (uintptr_t)( &*arr ) + ( x * B + y ) * sizeof(int) )
// ---- (uintptr_t)arr = (uintptr_t)&arr[0][0]
*(int*)( (uintptr_t)( &*(*(arr + 0) + 0) ) + ( x * B + y ) * sizeof(int) )
*(int*)( (uintptr_t)( &arr[0][0] ) + ( x * B + y ) * sizeof(int) )
*(int*)( (uintptr_t)&arr[0][0] + ( x * B + y ) * sizeof(int) )
// ---- decayed typeof(&arr[0][0]) = int*
*( &arr[0][0] + ( x * B + y ) )
(&arr[0][0])[x * B + y]
So:
arr[x][y] == (&arr[0][0])[x * B + y]
arr[x][y] == (&arr[0][0])[x * sizeof(*arr)/sizeof(**arr) + y]
On a sane architecture where sizeof(uintptr_t) == sizeof(size_t) == sizeof(int*) == sizeof(int**) and etc., and there is no difference in accessing data behind a int* pointer from accessing data behind int(*)[B] pointer etc. You should be safe with accessing one dimensional array when using a pointer to the first array member, as the operations should be equivalent ("safe" with exception for out-of-bound accesses, that's never safe)
Note, that this is correctly undefined behavior according to C standard and will not work on all architectures. Example: there could be an architecture, where data of the type int[A] are stored in different memory bank then int[A][B] data (by hardware, by design). So the type of the pointer tells the compiler which data bank to choose, so accessing the same data with the same to the value pointer, but with different pointer type, leads to UB, as the compiler chooses different data bank to access the data.
I need to rotate a matrix and call the funcion without using [],
I can't even think on a solution.
void _90DegClockwise(int *pS, int row, int col) {
for (int i = 0; i < row; ++i)
{
for (int j = i + 1; j < col; j++) {
int temp;
temp = (int)(pS);
*((int*)((pS + i) + j)) = (int*)((pS + j) + i);
(int*)((pS + j) + i) = temp;
}
}
}
I don't know how to insert a value to matrix or how to swap
To solve this, you need to understand how arrays work in C.
Lets say you have a 3 * 3 matrix, that is declared like this:
int matrix[3][3];
While you imagine this to be a square like this:
+---+---+---+
| 0 | 1 | 2 |
+---+---+---+
| 3 | 4 | 5 |
+---+---+---+
| 6 | 7 | 8 |
+---+---+---+
For the computer it is a consecutive "line" in memory looking like this:
+---+---+---+---+---+---+---+---+---+---+
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
+---+---+---+---+---+---+---+---+---+---+
^
|____matrix
And variable matrix holds the address of the first cell
So, if you want to access any cell without using the [] operator, you need to calculate the address of that cell.
Lets do this for the middle cell:
matrix[1][1];
This is the second cell of the second row, so you need to add the width of the first row to the start of the matrix, and then add one more cell from the start of the second row. And you want to derefernce the address to get to the value like so:
*(matrix + (3 * 1) + 1);
What if we wanted the middle cell of the third row? Same thing, but add width of two rows:
*(matrix + (3 * 2) + 1);
To sum up: if you want to access cell x in row y of the matrix you would calculate its address like this:
*(matrix + (with * y) + x);
You're mixing up the pointer and the dereferenced value in the 3 lines
In the first line temp = (int)(pS); you're assigning the pointer value to temp instead of the value that the pointer points to. Similarly you're also assigning the pointer value to the memory location like this *((int*)((pS + i) + j)) = (int*)((pS + j) + i); which makes no sense.
Then in the last line (int*)((pS + j) + i) = temp; doesn't work because you're assigning a value to an address instead of a memory location
Remember to use * to dereference a pointer to get the variable, i.e. the memory location the pointer points to. In C a[b] is equivalent to *(a + b) so just replace all those occurrences. I don't know why you do it "correctly" with *((int*)((pS + i) + j)) but didn't apply that to others
Even then you're calculating the index incorrectly. *((int*)((pS + i) + j)) is just pS[i + j] which is not the correct item you want. If you pass the 2D array as a 1D array you need to calculate the real index like this pS[i + j*width]
So to do
temp = pS[i + j*width];
pS[i + j*width] = pS[j + i*width];
pS[j + i*width] = temp;
just change it to
temp = *(pS + i + j*width);
*(pS + i + j*width) = *(pS + j + i*width);
*(pS + j + i*width) = temp;
You should enable all compiler warnings. They're very helpful and help you solve most of the above problem
I need help in understanding how we got the values in the table below for Loc3 and Loc4.
When I was making a table on my own I arrived to totally different entries for those columns.
Thank you!
int x = 42; /* x is at address 100 */
int y = 13; /* y is at address 104 */
int *p; /* p is at address 108 */
int **p2; /* p2 is at address 112 */
/* Location 1 */
p = &y;
p2 = &p;
/* Location 2 */
*p2 = &x;
**p2 = 11;
/* Location 3 */
*p = 12;
/* Location 4 */
For instance, x at loc3 becomes 11 because you set **p2 to 11, which modifies the value at that memory location. (double star is a pointer to a pointer). Ampersand gets the address.
To elaborate:
*p2 = &x;
**p2 = 11;
In Loc2 you set p2 = &p, which means p2 is now pointing to the address of p, which is 108.
But now in Loc3, you set what p2 is pointing to to the address of x. In other words, since p2 was pointing to the address of p, now you're saying that p should instead point to the address of x (which is also why p becomes 100).
Then **p2 modifies the value at that address of x to be 11 (through p), hence loc3's x value becomes 11.
Location 1:
int x = 42;
int y = 13;
int *p;
int **p2;
p or p2 don't point anywhere.
Location 2:
p = &y;
p points to y.
p2 = &p;
p2 points to p.
No changes to x or y.
Location 3:
*p2 = &x;
Since p2 points to p, dereferencing p2 and assigning a value to it changes p to point to x. Same as doing p = &x.
**p2 = 11;
Dereference once to get to p, dereference again to get to x, and assign 11 to it. Same as doing: x = 11 or *p == 11.
No change to y or p2.
Location 4:
*p = 12;
Dereference p to get to x and assing 12 to it. No change to y or p2 or p.
When you start out, p and p2 are uninitialized and contain indeterminate values, hence the ?? in both entries under Loc 1.
p = &y;
assigns the location of y (104) to p.
p2 = &p;
assigns the location of p (108) to p2. Note that the type of the expression &p is char **, which matches the type of the variable p2. So after these two statements, all of the following are true:
p2 == &p == 108 // all expressions have type char **
*p2 == p == &y == 104 // all expressions have type char *
**p2 == *p == y == 13 // all expressions have type char
x == 42
Next we execute
*p2 = &x;
From above we see that *p2 is equivalent to p, so this statement assigns the address of x (100) to p, so now we have
p2 == &p == 108
*p2 == p == &x == 100
**p2 == *p == x == 42
y == 13
Next we execute
**p2 = 11;
**p2 is equivalent to *p, which is equivalent to x, so we wind up assigning the value 11 to x:
p2 == &p == 108
*p2 == p == &x == 100
**p2 == *p == x == 11
y == 13
Finally we have
*p = 12;
*p is equivalent to x, so we're assigning the value 12 to x, leaving us with:
p2 == &p == 108
*p2 == p == &x == 100
**p2 == *p == x == 12
y == 13