Here is the problem:
#include <stdio.h>
int main()
{
int a[2][2] = { {6, 2}, {3, 4} };
int (**p)[2];
p = a;
for (int i = 0; i < 4; i ) {
printf("%p\n", (*p i));
printf("%d\n", *(*p i));
}
return 0;
}
I interpreted int(**p)[2];
as a double pointer to a 1D array of size 2.
I drew this conclusion because:
int *p[2];
means an array of integer pointers of size 2.int (*p)[2];
means an integer pointer pointing to a 1D array of size 2.
So,
int **p[2];
means an array of integer double pointers of size 2.int (**p)[2];
means an integer double pointer pointing to a 1D array of size 2.
Out of 1, 2, 3 and 4 statements which are true and which are needed to be corrected?
Consequently, what would be the output of this code?
I tried here.
CodePudding user response:
Your 'assertions' (1, 2, 3 and 4) are all essentially correct. However, I would use different, more specific terms and, especially, avoid the term, "double pointer". (That can be – and often is – mis-interpreted and/or misused.)
So:
int *p[2];
declaresp
as an array of two pointers to integers;int (*p)[2];
declaresp
as a pointer to an array of two integers;int **p[2];
declaresp
as an array of two elements, each of which is a pointer to a pointer to an integer;int (**p)[2];
declaresp
as a pointer to a pointer to an array of two integers.
… what would be the output of this code?
The code is ill-formed because of the p = a;
line. Furthermore, the line, printf("%d\n", *(*p i));
exhibits undefined behaviour, because there is a mismatch between the format specifier (%d
, which expects an int
argument) and the provided argument (*(*p i)
, which has type int*
).
A version of your code that does not exhibit undefined behaviour and may possibly do what you are looking for is the following (read the comments):
#include <stdio.h>
int main()
{
int a[2][2] = { {6, 2}, {3, 4} };
int(**p)[2];
int(*t)[2] = &a[0]; // a pointer to an array of 2 integers (1st half of "a")
// int(*t)[2] = a; // Works the same as "a" decays to address of 1st element
p = &t; // "p" is now (correctly) a pointer to that pointer
for (int i = 0; i < 2; i ) { // Going beyond 2 elements is UB (but MAY work)
printf("%p\n", (void*)(*p i)); // Arguments for "%p" should be void*
printf("%d\n", (**p)[i]); // Dereference "p" twice then get array element
}
return 0;
}
CodePudding user response:
Consequently, what would be the output of this code?
Undefined, as you access elements which do not belong to any object (outside the bounds).
I interpreted int(**p)[2]; as a double pointer to a 1D array of size 2.
It is a pointer to pointer to 2 elements int
array.
Double pointer is no very price term which is hard to interpret.
CodePudding user response:
The program is incorrect. The compiler should issue a message for thus assignment
p=a;
that there are used incompatible pointer types.
The array a declared like
int a[2][2] = {{6, 2}, {3, 4}};
is implicitly converted to a pointer of the type int ( * )[2]
in the expression statement shown above. So the right side operand has the type int ( * )[2]
while the left side operand has the type int ( ** )[2]
.
In this call of printf
printf("%p\n", (*p i));
printf("%d\n", *(*p i));
the expression *p
has the type int ( * )[2]
and the expression *( *p i )
has the type int[2]
. So in any case these calls do not make a sense.
You could write for example
#include <stdio.h>
int main()
{
int a[2][2] = { { 6, 2 }, { 3, 4 } };
int ( *p )[2];
p = a;
for ( int i = 0; i < 2; i )
{
printf( "%p\n", ( void * )( p i ) );
for ( int j = 0; j < 2; j )
{
printf( "%d\n", *( *(p i) j ));
}
}
return 0;
}
The program output migh look like
0x7ffc550ffc50
6
2
0x7ffc550ffc58
3
4
Or you could write
#include <stdio.h>
int main()
{
int a[2][2] = { { 6, 2 }, { 3, 4 } };
int ( *p )[2];
p = a;
for ( int i = 0; i < 4; i )
{
printf( "%p\n", ( void * )( *p i ) );
printf( "%d\n", *( *p i ) );
}
return 0;
}
The program output might look like
0x7ffc550ffc50
6
0x7ffc550ffc54
2
0x7ffc550ffc58
3
0x7ffc550ffc5c
4