I saw following piece of code in a legacy project.
/* token.c */
struct token id_tokens[MAX_TOKENS];
/* analyse.c (v1) */
extern struct token *id_tokens; /* Raised my eyebrow, id_token declares a pointer */
I insisted on changing analyse.c to contain the declaration as below:
/* analyse.c (v2) */
extern struct token id_tokens[]; /* I am happy with this. id_tokens declares array of unspecified size. */
I want v2 because pointer to T is not same as array of T. My friend's counter argumented that behaviour of both are same, so it doesn't matter whether I use v1 and v2.
Question 1: Does array of incomplete type deplete to a pointer?
Question 2: Is my friend right that both versions are behaviorally guaranteed to be equivalent?
So in your
analyse.c, following instructions would be generated with this declaration.So in your
analyse.c, following instructions would be generated with this declaration:Let's assume sizeof
id_token[0]is2byte and sizeof pointer toid_token[0]is4byte.Your later declaration may (mis)interprete the
id_tokens[0]&id_tokens[1]as an address and add some offset to it (which may be an existing or non-existing address, aligned or non-aligned address who knows).If it is your good day, program may crash or segfault immediately and you get a chance to fix the bug. If it is your bad day, program may just mess up with some other memory or communicate a wrong state to some module which can result in difficult to track bug and cause a nightmare.
Now I guess you understand why you got
(nil)as output in Mr. 32's answer.