0

EDIT
I've read the question and answers here: C pointer to array/array of pointers disambiguation. The answers there do not address the focus of my questions here as well as some of the answers already posted below. This is similar, but not a duplicate. The focus here is intended to be centered around explaining how the () changes the declaration. The focus in the link is broader, and in fact does not center around the impact and effect of () on a declaration such as the ones I include below.

What is the reason for the difference in the way

  1. int *a[5];

  2. int (*a)[5];

are created?

I am particularly interested in an explanation of how the () changes the declaration.

For example:

With 1)

a[0] = malloc(sizeof(int)); //compiles

But with 2) it does not. ( error: array type int [5] is not assignable )
Questions:
1) What is the effect of the () in 2)?
2) Why would declaration 2 ever be used over declaration 1?
(that is, why would declaration 2 ever be used?)

Community
  • 1
  • 1
ryyker
  • 22,849
  • 3
  • 43
  • 87
  • 1
    Check here http://cdecl.org/ – ViNi89 Jan 14 '16 at 20:56
  • @machine_1 - reference is close, I am also asking explicitly for insights on what the effect of `()` are on the declarations. – ryyker Jan 14 '16 at 21:14
  • 1
    It's not extremely unique compared to this question http://stackoverflow.com/questions/25790789/whats-the-difference-between-int-a5-and-inta5?lq=1 (and others) – Bo Persson Jan 14 '16 at 21:45
  • @BoPersson - that link, by one level of indirection, points to precisely the same link I referred to above. But thanks. – ryyker Jan 14 '16 at 21:47
  • @R Sahu - Please see my edit above. – ryyker Jan 14 '16 at 22:49
  • It is a duplicate still. The () makes it a different type - an array pointer, instead of an array of pointers. Basically you are just asking "what is an array pointer", a question that has been answered many times before. – Lundin Oct 10 '17 at 15:01

4 Answers4

5

They are not the same, rather quite different.

  1. int *a[5]; is an array of 5 int *s.

  2. int (*a)[5]; is a pointer to an array of 5 ints.

So, in the former case, a[0] is a pointer variable, hence, you can assign. But in the later, a[0] is an array type, and is not assignable, by definition.


Edit:

In case you're interested in the difference of type due to the presence of the (), have a look at the operator precedence. The [] has higher precedence over the *, so without an explicit (), the attachment of a goes to [] first.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
  • So, with `2`, a[0] does not exist, while with `1` it does? – ryyker Jan 14 '16 at 21:08
  • @ryyker; `a[0]` exists for both cases. When you declare a pointer `int i; int *p = &i;` then `p` is actually a pointer pointing to the first element of an array of length `1` and that element can be accessed either by `*p` or `p[0]`. – haccks Jan 14 '16 at 21:10
  • @ryyker `a[0]` anyways _exist_, in both the scenarios. – Sourav Ghosh Jan 14 '16 at 21:11
  • Operator precedence has nothing to do with declarations. There are no operators in either of those rows. – Lundin Oct 11 '17 at 06:31
4

In int (*a)[5];, () binds * to a and declare it as a pointer to an array. In int *a[5];, a binds to operator [] due to higher precedence than * and therefore declare it as an array of pointers.

So, in second case a is a pointer to an array and a[0] is an array (of type int [5]) and as per C rule arrays are not assignable. That's make the statement

a[0] = malloc(sizeof(int));  

illegal.

haccks
  • 104,019
  • 25
  • 176
  • 264
  • This addresses my question directly. I understand your explanation. Thank you. – ryyker Jan 14 '16 at 22:48
  • Why would anyone choose to use the second declaration type? `(*a)[5];` What purpose would there be to create this variable? – ryyker Jan 14 '16 at 23:02
  • 1
    This kind of declaration often used as function parameter where a 2D array is passed to a function. – haccks Jan 15 '16 at 11:12
  • Operator precedence has no relevance in a declaration. The declaration syntax is merely similar to some C operators. – Lundin Oct 10 '17 at 15:03
  • @Lundin can you explain it further? – haccks Oct 10 '17 at 15:09
  • Nothing in the expression is an operator. The `()` is a special form of declaration described in 6.7.6.1/6: "If, in the declaration ‘‘T D1’’, D1 has the form ( D ) then _ident_ has the type specified by the declaration ‘‘T D’’. Thus, a declarator in parentheses is identical to the unparenthesized declarator, but the binding of complicated declarators may be altered by parentheses." Similarly, the `[]` is an array declaration, not an operator. – Lundin Oct 11 '17 at 06:30
2

Because 1 is an array of pointers, while 2 is a pointer to an array of 5 int. Check like this

int (*a)[5];
int *b[5];

fprintf(stderr, "%zu\n", sizeof(a)); // Prints sizeof(void *)
fprintf(stderr, "%zu\n", sizeof(b)); // Prints 5 * sizeof(void *)
Iharob Al Asimi
  • 52,653
  • 6
  • 59
  • 97
2

This

int *a[5];

is a declaration of an array of 5 pointers of type int *.

So a[0] is an object of type int * and you may initialize it with a pojnter of type `void * in C

a[0] = malloc(sizeof(int)); //compiles

This`

int (*a)[5];

is a declaration of a pointer to an object of type int[5]. So a[0] is an array of 5 elements of type int . You may not assign an array with a pointer,

Thus this statement

a[0] = malloc(sizeof(int));

is invalid.

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