I have a 2D array (int s[4][2])and I created a pointer as int (*p)[2].
The pointer p is now assigned the address of 1st element of row within a for loop.
for (int i = 0; i<4; i++)
p = &s[i];
Now when I try to write the array elements data using dereferencing, I get wrong values.
printf ("%d \n", *p)
However, if I create another pointer and link that with the previous pointer
int *ptr = p;
and dereference pointer ptr I get correct values.
printf ("%d \n", *ptr)
When both the pointers are pointing to the same address why does one pointer (*ptr) work as expected and other (*p) does not return expected values?
If p is a pointer to array then *p is array of 2 ints (int[2]). So, you can't print an array element like this:
printf ("%d \n", *p);
To print the array elements through the pointer p, you need to do:
printf ("%d \n", (*p)[0]); /* first element */
printf ("%d \n", (*p)[1]); /* second element */
p is not a pointer to an int. It is a pointer to an array of two int. Therefore *p is also an array of two int. Since it is not an int, printing it using %d gives undefined behaviour.
You would not be able to "link" ptr to p because of a type mismatch (ptr is a pointer to int, and p (as already noted) is a pointer to an array of two int. Hence the assignment ptr = p would not compile. If you are forcing it to compile (e.g. ptr = (int *)p), then ptr and p will have the same value (i.e. they will identify the same location in memory) but different type (i.e. dereferencing them interprets the contents of that memory differently).
The value (ignoring type) of p will be the address of s[0][0]. Similarly, the value of ptr will be the address of s[0][0].
As a result printf("%d\n", *ptr) will print the value of s[0][0].
When both the pointers are pointing to the same address why does one pointer (*ptr) work as expected and other (*p) does not return expected values?
*p evaluates to an int[2], an array.
Passing an int[2], an array to a function, results in passing a pointer the array's 1st element, a int*.
*ptr evaluates to an int.
Passing an int to a function, results in passing an int to a function ... :-)
By
int (*ptr)[2] ; // means int[2]<-(*ptr)
You got pointer to an array of two integers
The pointer p is now assigned the address of 1st element of row
within a for loop.
This is not correct, technically p is assigned the address of the entire int[2] block (Hint : use sizeof to verify the size).
What is the problem with printf ("%d \n", *ptr)
*ptr by itself doesn't contain a integer but it holds the address of the first element of int[2] ie *ptr itself is a pointer.
A working example would be
int main(void)
{
int i;
int s[4][2]={{0,1},{2,3},{4,5},{6,7}};
int (*ptr)[2];
for(i=0;i<4;i++)
{
ptr=&s[i];
printf("i:%d\n",i);
printf("Element 1 : %d\n",(*ptr)[0]);
printf("Element 2 : %d\n",(*ptr)[1]);
/* Replacing (*ptr)[1] with *((*ptr)+1) gives you the same
* results
*/
}
return 0;
}
Output
i:0
Element 1 : 0
Element 2 : 1
i:1
Element 1 : 2
Element 2 : 3
i:2
Element 1 : 4
Element 2 : 5
i:3
Element 1 : 6
Element 2 : 7
Related
Below is a code snippet and the outputs:
int main()
{
int A[2][3] = {{1100, 1200, 1300}, {1400, 1500, 1600}};
int (*p)[3], (**q)[3];
p = A;
q = A;
printf("*p is : %d\n", *p);
//Output : *p is : -547221600
printf("*q is : %d", *q);//Why ?
//Output : *q is : 1100
}
p is a pointer to integer array of size 3. *p + i points to ith array in A i.e. A[i].
What would happen if instead I use double pointers (q in the above code).
I am unable to understand that why *q gives 1100 as the value.
For starters this assignment
q = A;
is incorrect because the left operand (having the type int ( ** )[3]) and the right operand (having the type int ( * )[3] after the implicit conversion of the array designator to a pointer to its first element) have different types and there is no implicit conversion between the types.
The compiler can issue an error like this
error: assignment to ‘int (**)[3]’ from incompatible pointer type ‘int (*)[3]’
You could write instead
q = &p;
In this call of printf
printf("*p is : %d\n", *p);
there is used an incorrect argument. The type of the expression *p is int[3]. So in fact you are trying to output a pointer (due to implicit conversion of the array designator to a pointer to its first element) using the conversion specifier %d that is designed to output integers.
Here is a demonstrative program.
#include <stdio.h>
int main(void)
{
int A[2][3] = {{1100, 1200, 1300}, {1400, 1500, 1600}};
int (*p)[3], (**q)[3];
p = A;
q = &p;
printf( "A is : %p\n", ( void * )A );
printf( "*p is : %p\n", ( void * )*p );
printf( "*q is : %p\n", ( void * )*q);
return 0;
}
Its output might look like
A is : 0x7ffdb1c214e0
*p is : 0x7ffdb1c214e0
*q is : 0x7ffdb1c214e0
That is the first call of printf output the initial address of the first element A[0] (of the type int[3]) of the two-dimensional array.
The second call of printf outputs the address of the first element of the first "row" of the two-dimensional array that is &A[0][0].
The third call of printf outputs the value stored in the pointer p that is the address of the first "row" of the two-dimensional array A.
If you want to output the first elements of the array A using the pointers then the program can look the following way.
#include <stdio.h>
int main(void)
{
int A[2][3] = {{1100, 1200, 1300}, {1400, 1500, 1600}};
int (*p)[3], (**q)[3];
p = A;
q = &p;
printf( "**p is : %d\n", **p );
printf( "***q is : %d\n", ***q);
return 0;
}
Now the program output is
**p is : 1100
***q is : 1100
p is a pointer to integer array of size 3.
Correct.
*p + i points to ith array in A i.e. A[i].
Incorrect. p + i would be a pointer to an array.
When you indirect through the pointer to array, the result is an array, and when you add an integer to an array, the array decays to pointer to element of that array and since *p is an array of integers, the decayed pointer points to an integer element of the array. Thus, the result of *p + i is a pointer to an integer (i'th sibling of the first element of the first array).
What would happen if instead I use double pointers (q in the above code).
I assume that by substituted above code, you mean *q + i.
If you have a pointer to a pointer to an array, then indirecting through the pointer results in a pointer to an array. Adding an integer to pointer to an array gives you pointer to an array that is a sibling.
q = A;
This assignment is ill-formed in C++. An array of arrays of integers is not convertible to a pointer to pointer to an array.
printf("*p is : %d\n", *p);
printf("*q is : %d", *q);//Why ?
%d is an invalid format specifier for int* as well as for a int (*)[3]. By using invalid format specifier, the behaviour of this program is undefined. That explains all of the behaviour.
I don't understand why when dereferencing a pointer to an array, the result is the address of the first value of the array
int array[2][2] = {{0,1},{0,1}};
int (*p)[2];
p = array;
p = address of a[0][0], p+1 = address of a[1][0],
*p = address of a[0][0], (*p)+1 = the address of a[0][1];
I understand that p is a pointer to an array of 2 integers, not a pointer to an integer. But if we print out the value of p, it's still the address of an integer. I want to know what's going on under the hood? Is p a pointer to an array of pointers? So we have to dereference it twice to get the value of the integer its pointing?
A pointer to an int,
int* p;
is a variable, stored in a location, that contains the address of another variable (int).
When we dereference it, we get the value of that variable. How does this process work exactly with a pointer to an array?
The address of an array is the same as the address of its first element.
Given the definition int array[2][2] = {{0,1},{0,1}};, the compiler arranges some location in memory to contain the int values 0, 1, 0, and 1. Let’s say that location has address 1000, and the int value 0 is stored in bytes 1000-1003, 1 is stored in 1004 to 1007, 0 is stored in 1008 to 1011, and 1 is stored in 1012 to 1015.
Where does the element array[0][0] start in memory? At location 1000.
Where does the array array start in memory? At location 1000.
Where does the array array[0] start in memory? At location 1000.
The array starts in memory at the same location its first element starts in memory. Also, array[0], which is itself an array, starts at the location 1000.
So, after p = array;, p points the location 1000. And the element array[0][0] also starts at location 1000. So, when you print p, as with printf("%p\n", (void *) p);, it is unsurprising you get the same result as when you print the address of array[0][0], as with printf("%p\n", (void *) &array[0][0]);.
An array is automatically converted to the address of its first element.
Next, let’s consider *p. The type of p is int (*)[2], a pointer to an array of 2 int. Therefore, *p is an array of 2 int.
In particular, *p is an array. Suppose we attempt to print it by passing it as an argument to printf. What happens?
In C, when an array is used in an expression, it is automatically converted to the address of its first element (except when the array is the operand of sizeof or unary & or is a string literal used to initialize an array). So, if you use *p as an argument to printf, it initially means array[0], but that array is converted to the address of its first argument. So passing *p as an argument actually passes &array[0][0] (or, equivalently &(*p)[0]).
Thus, printf("%p\n", (void *) *p); will print the same address as printf("%p\n", (void *) &a[0][0]);.
Value at an array can be accessed using
array[i] = *(array+i) (expansion of [i]).
Similarily, (*p)[i] = *(*(p+i)). So, we need to dereference twice to access the value.
If you want to access, array[0][0], you have to use *(*(p+0)+0) = **p;,
Similarily, array[0][1] can be accessed using *(*(p+0)+1) = *((*p)+1);
Note, *p points to first row (stores address of array[0][0]), and *(p+1) points to second row (stores address of array[1][0]).
Please check the below code :
#include <stdio.h>
int main()
{
int array[2][2] = {{1, 2}, {3, 4}};
int(*p)[2];
p = array;
printf("The address of array[0][0] is %p \n",&array[0][0]);
printf("The address of *p is %p \n",*p);
printf("The address of array[1][0] is %p \n",&array[1][0]);
printf("The address of *(p+1) is %p \n",*(p+1));
printf("The value of array[0][0] is %d \n",array[0][0]);
printf("The value of **p is %d \n",**p);
printf("The value of array[0][1] is %d \n",array[0][1]);
printf("The value of *((*p)+1) is %d \n",*((*p)+1));
return 0;
}
The output is:
The address of array[0][0] is 0x7fff6e8781a0
The address of *p is 0x7fff6e8781a0
The address of array[1][0] is 0x7fff6e8781a8
The address of *(p+1) is 0x7fff6e8781a8
The value of array[0][0] is 1
The value of **p is 1
The value of array[0][1] is 2
The value of *((*p)+1) is 2
I know there are many similar questions, but I can't find an answer.
When passing the two-dimensional [3] [4] array to the function in my code below, how does the compiler know how far to increment the pointer, in the case of the last printf() where we are incrementing 3 x 4 memory locations, if the number 3 is missing in the function argument?
I mean, why is only arr [] [4] sufficient and not [3] [4]? Thanks
#include <stdio.h>
#include <stdlib.h>
int Fun(int arr[][4])
{
printf("%p\n", arr); // address of first element
printf("%p\n", arr[0] + 1); // address increments by 4, pointing to next "inner array"
printf("%p\n", arr + 1); // how does it know to increment address by 3 x 4 here? The complete array size
}
int main()
{
int arr[3][4] =
{
1,2,3,4,
5,6,7,8,
9,10,11,12
};
printf("%p\n", arr);
printf("%p\n", arr[0] + 1);
printf("%p\n", arr + 1);
printf("Passing to function\n");
Fun(arr);
return 0;
}
First, Fun should be defined with:
int Fun(int arr[][4])
rather than what you have, int Fun(int* arr[][4]);.
Next, when Fun(arr) is evaluated, arr is automatically converted from an array of 3 arrays of 4 int to a pointer to an array of 4 int. Similarly, in the declaration of Fun, int arr[][4] is automatically adjusted to be a pointer to an array of 4 int. So the argument type and the parameter type will match if you declare Fun correctly.
You could also declare Fun as:
int Fun(int (*arr)[4])
This is the same thing as above, due to the automatic adjustment that would be applied to the declaration above. Note that the asterisk here is grouped with the arr by the parentheses. This makes it a pointer to an array of int, rather than an array of pointers to int.
Now, as to what will be printed, in main:
printf("%p\n", arr);
In this statement, arr will be automatically converted to a pointer to its first element, so it becomes a pointer to an array of 4 int. Then the value of this pointer is printed. Note: When printing pointers, technically you should convert them to const void * or void *, as with printf("%p\n", (const void *) arr);. However, omitting this likely does not cause a problem at the moment.
printf("%p\n", arr[0] + 1);
In this statement, arr[0] is the first element of arr. That first element is an array of 4 int, and it is automatically converted to be a pointer to its first element. So arr[0] becomes a pointer to the first int. Then adding 1 advances the pointer to the next int. The result is likely an address four bytes beyond arr, depending on your C implementation. (It could be a different number of bytes, but four is the most common today.)
printf("%p\n", arr + 1);
In this statement, arr is converted to a pointer to its first element, an array of 4 int. Adding 1 advances to pointer to the next element, which is the next array of 4 int. So this likely adds 16 bytes to the address.
Then, in Fun:
printf("%p\n", arr); // address of first element
Here arr is a pointer to an array of 4 int. Its value is printed, yielding the same address as for the corresponding printf in main.
printf("%p\n", arr[0] + 1); // address increments by 4, pointing to next "inner array"
Here arr[0] is the object pointed to by arr, which is an array of 4 int. Since it is an array, it is automatically converted to a pointer to its first element, which is an int. So this points to the first int. Then adding 1 advances to the next int, and this again yields the same address as the corresponding printf in main.
printf("%p\n", arr + 1); // how does it know to increment address by 3 x 4 here? The complete array size
In this case, arr is a pointer to an array of 4 int, and adding 1 advances it to the next array of 4 int, so the result is likely 16 bytes beyond the value of arr, and this again yields the same address as the corresponding printf in main.
If you saw different values for the printf statements in Fun and main, this was likely because of the incorrect declaration with int* and because int * is eight bytes in your C implementation, compared to four for int. That error would have doubled some of the increments. You should not have seen any multiple of three in the increments.
Regarding the first dimension, Fun does not need to know the first dimension because it never advances any pointers by units of the first dimension. It receives only a pointer to an array of 4 int, and it does not need to know that there are 3 such arrays there.
The detailed answer by Eric Postpischil clearly shows all the issues in OP's code.
I'd like to note that passing a pointer to the correct type would let the compiler doing the right pointer arithmetic:
#include <stdio.h>
#include <stdlib.h>
void Fun(int (*arr)[3][4])
{
printf("Address of the first element: %p\n", (void *)*arr);
printf("Address of the second row: %p\n", (void *)(*arr + 1));
printf("Address after the last element: %p\n", (void *)(arr + 1));
}
void Fun_vla(size_t rows, size_t cols, int (*arr)[rows][cols])
{
printf("Address of the first element: %p\n", (void *)*arr);
printf("Address of the second row: %p\n", (void *)(*arr + 1));
printf("Address after the last element: %p\n", (void *)(arr + 1));
}
int main()
{
int arr[3][4] =
{
{1,2,3,4},
{5,6,7,8},
{9,10,11,12}
};
Fun(&arr);
puts("");
Fun_vla(3, 4, &arr);
return 0;
}
typedef char trgm[3];
char test[2][3] = {'a','b','c','d','e','f'};
int main(void)
{
trgm *t;
t = test;
printf("%c\n",*(char *)t);
printf("%c\n",*(char *)*t);
printf("%c\n",**t);
return 0;
}
the output of three printf is same. I don't understand why the t and *t are same? what does complier do internal?
There are three paths of interpretation of the same value - the starting address of the memory extent occupied by the array. So dereferencing the value casted to char * you will get the value of the first element of the type char of the array.
You can think of an array variable as containing the memory address of its first element. In your case since the array is a 2D array, the "first element" t[0] is in-fact pointer to the 'first row'. Note that in terms of memory there is no special storage for element t[0] and t[1], it gets converted to appropriate memory offset, but it helps to think that way. Hence when you deference the pointer (*t), you get the same value as you would get for the array variable.
t = [0] --> 'a','b','c'
[1] --> 'd','e','f'
Try this printf("%p %p %p\n", t,*t, t[0]);, you will get same value for all.
When you declare the typedef char trgm[3];, then trgm refers to *an array of char [3]`. This is important.
When you declare trgm *t = test, the pointer t is a pointer to array of char [3]. By setting t = test; you make t a pointer that points to the first row of test (essentially equivalent to test[0]. Since an array variable holds (or points to) the first element of test, both t and test point to the same value. Dereferncing the either the pointer t or test (e.g. *t or *test) will access the first element of test.
Now since t is a pointer to array of char [3], it is a pointer with two-levels of indirection and can therefore be dereferenced twice (as can test). Take test[row][col]. Let's look at the pointer equivalent for the array. test can be written as
*(*(test + col) + row)
(both col and row are 0 when referencing the first element (e.g. test[0][0]) so the above is simply
*(*(test + 0) + 0)
note: anything plus 0 is just that thing again, so it simplifies to:
**test
For t it is just:
(*t)[col] /* to index cols 0 - 2 */
It too can be rewritten as:
*((*t) + col)
With col being zero for the first element, you get
**t
However, t by pointing to the first row, allows pointer arithmetic (e.g. t = t + 1;, or just t++) to update t to point to the second row, and so on.
So, in sum, whether you are looking at test or you are looking at t, both initially reference the address for the first element in test, both are (or can be considered) pointers with two levels of indirection, and dereferencing each once, or twice, will still point at the original element in test. You can use t to access all values in your array, for instance:
for (; t < &test[2]; t++)
printf (" %c, %c, %c\n", (*t)[0], (*t)[1], (*t)[2]);
putchar ('\n');
Which will output:
a, b, c
d, e, f
Lastly, there is no need to make test a global variable. Avoid global variables to reduce the chance of name collision. Declare test in main() and pass it pointer to it to any other function it is required.
Putting that altogether, you could do something like:
#include <stdio.h>
typedef char trgm[3];
int main(void)
{
char test[][3] = {{'a','b','c'},
{'d','e','f'}};
trgm *t;
t = test;
printf("%c\n",*(char *)t);
printf("%c\n",*(char *)*t);
printf("%c\n",**t);
for (; t < &test[2]; t++)
printf (" %c, %c, %c\n", (*t)[0], (*t)[1], (*t)[2]);
putchar ('\n');
return 0;
}
Example Use/Output
$ ./bin/p2x3
a
a
a
a, b, c
d, e, f
Look things over and let me know if you have any further questions.
If I run the following on OS X:
int main (void)
{
int* n; // initialise(declare) pointer
*n = 20; // the value in address pointed to by n is 20
printf("n: %i, n&: %i\n", n, &n);
return 0;
}
I get:
n: 1592302512, n&: 1592302480
Why the differing values?
Why do pointer and &pointer have different values?
The expression &n yields the address of n itself, while n evaluates to the value of the pointer, i.e. the address of the thing it points to.
But note that you have undefined behaviour First of all, because you are de-referencing an uninitialized pointer. You need to make n point somewhere you can write to.
For example,
int* n;
int i = 42;
n = &i;
// now you can de-reference n
*n = 20;
Second, you have the wrong printf specifier for &n. You need %p:
printf("n: %i, &n: %p\n", n, &n);
int* n declares a variable called n which is a pointer to an integer.
&n returns the address of the variable n, which would be a pointer to a pointer-to-integer.
Let's say we have the following code:
int a = 20; // declare an integer a whose value 20
int* n = &a; // declare a pointer n whose value is the address of a
int** p = &n; // declare a pointer p whose value is the address of n
In this case we would have the following:
variable name | value | address in memory
a | 20 | 1592302512
n | 1592302512 | 1592302480
p | 1592302480 | who knows?
In your code
int* n; //initialization is not done
*n = 20;
invokes undefined behavior. You're trying to de-reference (write into) uninitialized memory. You have to allocate memory to n before de-referencing.
Apart form that part,
n is of type int *
&n will be of type int **
So, they are different and supposed to have different values.
That said, you should use %p format specifier with printf() to print the pointers.
Just as an alternative, let me spell this out a different way.
char *ptr;
char c='A';
ptr = &c;
In this code, here's what's happening and what values are found when we qualify ptr in different ways.
ptr itself contains the address in memory where the char c variable is located.
*ptr dereferences the pointer, returning the actual value of the variable c. In this case, a capital A.
&ptr will give you the address of the memory location that ptr represents. In other words, if you needed to know where the pointer itself was located rather than what the address is of the thing that it points to, this is how you get it.