0

There is a post where different pointer notations are explained:

int* arr1[8]; // An array of int pointers.
int (*arr2)[8]; // A pointer to an array of integers
int *(arr3[8]); // The same as the first one

But it is also possible to define this:

int (*arr4[8])

Here everything except the datatype name is enclosed with parentheses. How is it different from the firts three options?

I tried to enclose it like (int *arr4[8]) as well, but seems like this is not valid in C.

I'm also curious about constructions like this:

int (*arr5[8])[8]

Not sure, but I presume this is something like an array of pointers to an array of integers. If I need to specify a pointer to such construction, I reckon this is something like this:

int (*(*arr5[8]))[8]

And if I throw the outermost parentheses aside, I guess this is something like an array of pointers to an array of pointers to integers, is it?

int *(*arr5[8])[8]

Is all that correct? Thanks in advance!

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
Kaiyaha
  • 448
  • 3
  • 9

2 Answers2

1

You may enclose declarators in parentheses.

This declaration

int (*arr4[8]);

declares an array of 8 elements of the type int *. It is the same as to write

int * arr4[8];

As for this declaration

int (*(*arr5[8]))[8];

then to make it clear consider the following demonstrative program.

#include <stdio.h>

int main(void) 
{
    int a1[8] = { [0] = 10 };
    int a2[8] = { [0] = 20 };
    
    int ( *p1 )[8] = &a1;
    int ( *p2 )[8] = &a2;
    
    int (*(*arr5[8]))[8] =
    {
        &p1, &p2
    };
    
    printf( "%d\n", ( **arr5[0] )[0] );
    printf( "%d\n", ( **arr5[1] )[0] );
    
    return 0;
}

The program output is

10
20

That is this declaration

int (*(*arr5[8]))[8]

declares an array of pointers to pointers to arrays of the type int[8].

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
1

int (*arr4[8])

Here everything except the datatype name is enclosed with parentheses. How is it different from the firts three options?

The only times parentheses matter is when they change the default precedence of operators. Postfix [] and () have higher precedence than unary * in both declarators and expressions, so *arr4[8] is parsed as *(arr4[8]). (*arr4[8]) doesn't affect the precedence of either * or [], so it's identical to writing *(arr4[8]) and *arr4[8]. However, with (*arr3)[8], they do change that precedence, explicitly grouping the * operator with arr.

I tried to enclose it like (int *arr4[8]) as well, but seems like this is not valid in C.

It is not - the syntax doesn't allow it.

int (*arr5[8])[8]

Not sure, but I presume this is something like an array of pointers to an array of integers.

Precisely speaking, arr5 is an 8-element array of pointers to 8-element arrays of int. Graphically, it would look something like this:

      +---+                     +---+---+---+---+---+---+---+---+     
arr5: |   | arr5[0] ----------> |   |   |   |   |   |   |   |   |
      +---+                     +---+---+---+---+---+---+---+---+
      |   | arr5[1] --------+
      +---+                 |   +---+---+---+---+---+---+---+---+
      |   | arr5[2] ------+ +-> |   |   |   |   |   |   |   |   |
      +---+               |     +---+---+---+---+---+---+---+---+
       ...                |     
                          |     +---+---+---+---+---+---+---+---+
                          +---> |   |   |   |   |   |   |   |   |
                                +---+---+---+---+---+---+---+---+

You would index each element as (*arr5[i])[j] - you don't want to index into each arr5[i], you want to index into what each arr5[i] points to. The declarator tells you this up front - you don't have to puzzle it out on your own. The structure of the declarator mirrors the structure of the expression.

Note that this declaration doesn't create the 8-element arrays of int - it only creates an 8-element array of pointers. You would either need to dynamically allocate the memory for each arr5[i] to point to, like:

for ( size_t i = 0; i < 8; i++ )
  arr5[i] = malloc( sizeof *arr5[i] ); // sizeof *arr5[i] == sizeof (int [8])

or have a bunch of arrays already declared:

int foo[8];
int bar[8];
int bletch[8];
...
int (*arr5[8])[8] = { &foo, &bar, &bletch, ... };
John Bode
  • 119,563
  • 19
  • 122
  • 198