Different errors in C code in different compilers

0

In the following code below there is an error that the LCCx86 compiler for Windows claims to exist, but I have copied the codes of a C class I am watching.

Link to the lesson for anyone interested

In the C Online compiler link It displays other errors!

  • What is the error?
  • Why do different compilers display different errors?
  • Is language not standardized?
  • Or am I not understanding the errors?
  • #define MAX 50;
    
    typedef int TIPOCHAVE;
    
    typedef struct {
        TIPOCHAVE chave;
    } REGISTRO;
    
    typedef struct {
        REGISTRO A[MAX]; //Linha 10
        int nroElem;
    } LISTA;
    

    Some of the errors:

    PS D:\Cursos\C> lcc .\arranjos.c
    Error arranjos.c: 10  syntax error; found ';' expecting ']'
    Error arranjos.c: 10  syntax error; found ']' expecting '}'
    Error arranjos.c: 10  skipping ']'
    Error arranjos.c: 10  empty declaration
    
        
    asked by anonymous 31.07.2017 / 14:31

    2 answers

    3

    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.     

    31.07.2017 / 16:40
    5
      

    What is the error?

    It has ; in #define , and should not have, this is wrong syntax. If class taught so run away from it. In any compiler this does not do what you want.

      

    Why do different compilers display different errors?

    Because they are different. They can handle as they please with the code as long as they obey the specification.

      

    Is the language not standardized?

    Yes, and as long as the compiler respects what was specified it can work as it wishes. If the specification said every detail to be followed it would not have to have more than one compiler. Each one does what it thinks best and each programmer chooses the compiler that best suits him.

    The compiler can even add new things.

    It has compilers that do not even meet the specification. They say they compile C, but they do not say they meet the standard. Nobody is obliged to meet the standard, just can not say that it answers unattended. Even so, I do not know if anything would happen if I lie.

      

    Or am I not understanding the errors?

    That's only you can answer.

    The error

    See What is undefined behavior, unspecified and defined by the implementation? .

    But neither is the case. The compiler can handle the errors as you want, you can check in the order you want, you can stop whenever you want.

    As we do not have the errors in the two compilers we can not compare the behaviors.

    It is a fact that an error can trigger others and solving this, solves all, so much that there is only one and it showed 4, it would possibly show others if the code was bigger or if the compiler did not stop when it already coiled a lot.

    And the error in one place generated error in another. First understand how #define works and alternatives to it , which I would have used in this case. I consider it almost obsolete.

    Then when the code is compiled, there is a processing of the text by changing all texts MAX by 50; which is the text that is written in your code. Let's see the first occurrence of it:

    REGISTRO A[MAX];
    

    Once processed it would be

    REGISTRO A[50;];
    

    This ; within the array declaration is forbidden in any compiler.

    There are compilers who "perceive" the type of error and can give a better message, that is the prerogative of it to do, the language does not say how the error should be treated, what the message should be, none of that. So some compiler can give a message indicating the error in the right place, that is in line 1, since the compiler can understand that this is a common error. But most will prefer to give the error where it actually occurred.

    Smarter compilers are harder to develop, and often take longer to compile until you find the green bug. In general only compilers that have a lot of effort is smart, so I only recommend using "exotic" compilers if it is really necessary.

    And then an error triggers the others since the compiler understands that after 50 is closing the line. So the syntax of that line is wrong because it was not closed, and the next line of code is wrong because no new line starts with a ] , and it gets lost thinking that it would close the structure and still end up with a% loose that is closing anything, since there was an earlier closing where it should not.

    By that I say and repeat: the person does not know how to program until he understands all the characters that are in his code, until the space is blank. Everything has influence on the code, both compiler and readability.

    This code compiles:

    #define MAX 50
    
    typedef int TIPOCHAVE;
    
    typedef struct {
        TIPOCHAVE chave;
    } REGISTRO;
    
    typedef struct {
        REGISTRO A[MAX]; //Linha 10
        int nroElem;
    } LISTA;
    
    int main(void) {
        // your code goes here
        return 0;
    }
    

    See running on ideone . And no Coding Ground . Also put it in GitHub for future reference .

        
    31.07.2017 / 14:47