Home > Back-end >  What is " int (**p)[2]; "?
What is " int (**p)[2]; "?

Time:07-18

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:

  1. int *p[2]; means an array of integer pointers of size 2.
  2. int (*p)[2]; means an integer pointer pointing to a 1D array of size 2.

So,

  1. int **p[2]; means an array of integer double pointers of size 2.
  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:

  1. int *p[2]; declares p as an array of two pointers to integers;
  2. int (*p)[2]; declares p as a pointer to an array of two integers;
  3. int **p[2]; declares p as an array of two elements, each of which is a pointer to a pointer to an integer;
  4. int (**p)[2]; declares p 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
  • Related