When [] appears in a function definition or prototype, it's a placeholder for a pointer and is considered to be an incomplete type.
Just to be clear, it's NOT an array. That means within the function you cannot know the size of the array passed it. This is because it resolves to a pointer.
Thus, in C, wherever an array is passed, the size has to be passed too, or some other indication of the size.
In your example, an array (argv) is passed along with the array's size (argc).
This is why strncpy is safe and strcpy isn't; snprintf is safe and sprintf isn't; etc.
When [] is used in a string declaration, the size is worked out by the compiler. So the size is known.
a is an array of char, 6 elements long and initialised with 'orbis\0'
This is an error, and later compilers will flag it as such.
p is a mutable pointer to a constant string. Wth any lock, the string will be placed in a read-only segment and any attempt to write to it will generate a SEGFAULT. If you're unlucky, you won't get any warning at all.
You can use [] on both a and p, but the write into p is an error. So luckily (believe it or not), you're seeing and error as you cannot change anything in "tertius" thru p.