In Short:
The 3rd scenario is different because, the type of the pointer variable mismatches - the extern declares a pointer to an array of ints with an unknown size(incomplete type), and the definition is for the same variable, but as a pointer to an array of 5 ints, which are different (valid) types according to the standard.
Detailed:
The first scenario is staightforward:
the extern int* a only declares the existence of a variable of type int *.
the second line defines the same variable.
the second scenario:
I read through the standard again, and this is what it says:
The declared type of an array object might be an array of unknown size
and therefore be incomplete at one point in a translation unit and
complete later on; the array types at those two points (“array of
unknown bound of T” and “array of N T”) are different types
I believe what this means is that the definition of the array with a subscript completes the previous declaration of the variable as an array with unknown size(no subscript) - this is what is happening in scenario 2.
the third scenario:
Using the same meaning as from the standard, the array types at those two points are of different types.
Hence case 3 fails, because the first and second declarations would then be declaring the same pointer variable as pointer to different types, leading to a "redefinition with different types" error
[Edited answer after re-reading the standard]
extern int (*a)[5]? There is a trick with the empty[]that sometimes are saw as another pointer, so your code maybe is interpreted asextern int (**a).extern int (*a)[];, what does your compiler give assizeof aandsizeof *a? I have a vague feeling that at least one of these two expressions will not compile because it tries to take the size of an incompletely declared object.acannot be completed. That's in the quote of your earlier question.