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!

6
  • 1
    cdecl.org Commented Oct 21, 2020 at 19:58
  • 2
    int (*arr4[8]) is the same as int* arr1[8]; Commented Oct 21, 2020 at 19:59
  • Using typedef is very useful when nesting these deeply as in your last examples. Commented Oct 21, 2020 at 20:00
  • @Barmar well, yes, that enhances readability. Still, did I interpret those constructions right? Commented Oct 21, 2020 at 20:02
  • Use the site linked to above, that's what I would do if I were going to answer the question. Commented Oct 21, 2020 at 20:04

2 Answers 2

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, ... };
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, especially for explaining the precedence
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].

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.