Preprocessing
The problem is this semicolon:
#define MAX 50;
The reason is that #define
works (speaking in a somewhat simplistic way) by copying and pasting in the rest of the code the occurrences of the first word by the rest. They are resolved in a step called preprocessing, which is intended to resolve all #define
s and #include
s and also eliminate comments. Preprocessing occurs on top of the source code when making text overrides. The compilation actually starts over the already preprocessed source code. You may even see the output of the preprocessor when invoking your compiler with the correct flags. In the case of LCC it looks like this:
lcc -E arranjos.c
GCC is the same way:
gcc -E arranjos.c
This command will preprocess the file arranjos.c
.
In the case of your program, the preprocessor will replace MAX
with 50;
, producing this:
typedef int TIPOCHAVE;
typedef struct {
TIPOCHAVE chave;
} REGISTRO;
typedef struct {
REGISTRO A[50;];
int nroElem;
} LISTA;
And it's this code above that the real compiler will see. Look at line 10:
REGISTRO A[50;];
Note that this semicolon within the array dimension causes the compiler to choke.
Finally, different compilers will give different errors because the language specification tells you how the compiler should interpret well-formed code and how to make it into an executable. However, when what occurs is malformed code, the specification speaks little. Therefore, what the compiler must do against malformed code ends up being in charge of who developed the compiler, and thus, different compilers will give different errors.
Errors
In this case, the first mistake you have is very clear:
syntax error; found ';' expecting ']'
This error says that the compiler found a semicolon that should not be there and expected a date-bracket.
Subsequent errors occur because the compiler ended up getting confused by the first error, but I suppose his error-recovery strategy was to pretend that what he wanted to find but did not find would actually be there. So, when he found ;
when he expected a ]
, he pretended that:
typedef struct {
REGISTRO A[50;];
int nroElem;
} LISTA;
It was actually this:
typedef struct {
REGISTRO A[50];];
int nroElem;
} LISTA;
In other words, he pretended / kicked / guessed that you had forgotten to put ]
.
But then he finds another ]
more. At this point, he expected the definition of another field of struct
or }
of the end of struct
. The second option is the simplest, so it launched as an error this:
Error arranjos.c: 10 syntax error; found ']' expecting '}'
And then to recover, he pretended that }
was there:
typedef struct {
REGISTRO A[50];}];
int nroElem;
} LISTA;
In this step, the compiler again finds the ]
there silently, without closing anything. The solution is to skip it by issuing the error Error arranjos.c: 10 skipping ']'
and pretending that the code looked like this:
typedef struct {
REGISTRO A[50];};
int nroElem;
} LISTA;
With these changes, he ends up seeing typedef
like this:
typedef struct {
REGISTRO A[50];};
And in this case, it lacked the name that comes before the latter ;
. So he gives one more error:
Error arranjos.c: 10 empty declaration
After that, the compiler should produce other errors. In particular, he will think that nroElem
is out of struct
and will see }
after being silly.
In fact, you only had one error, which was ;
within #define
. However, due to the improper compiler recovery strategy, he ended up seeing a lot of different errors where he had only one because he got confused. Each compiler has a different error strategy (again, the C language specification focuses on well-formed code and talks little about how to deal with malformed code).
On the other hand, you can not blame the compiler because there is no optimal error recovery strategy. When the code is malformed, the compiler loses the structural guarantees that the language would give and it has to try to guess what the programmer wanted, and in many cases this process of guessing can lead to very bad results. For example, try compiling a code in Python, Java or any other language with the C compiler to see that any compiler will get pretty confused and that whenever it tries to make an effort to understand something, it will end up getting even more confusing. / p>
Finally, GCC should use a better error recovery strategy in this case (in other cases it may be different). Here is the output of GCC with this code:
arranjos.c:1:15: error: expected ‘]’ before ‘;’ token
#define MAX 50;
^
arranjos.c:10:16: note: in expansion of macro ‘MAX’
REGISTRO A[MAX]; //Linha 10
^~~
In particular, the GCC is smart (at least in this case) to know that the error occurred within a macro (that is, a #define
) and give error messages more precise than the LCC without being confused.