Search code examples
arrayscgcccompilationc89

Why is there no compilation error with those array declarations (C89-C90)?


I want to show that arrays can't be defined with a variable for the length in C89 or C90.

I use GCC on Windows from TDM GCC:

C:\TDM-GCC-64\bin> .\gcc.exe --version
gcc.exe (tdm64-1) 10.3.0

My compilation options are: gcc.exe -Wall -g -ansi -save-temps -c

I tried:

int main()
{
    int i;
    int tab[i];

    tab[0] = 10;

    return 0;
}

But it compiles fine:

gcc.exe -Wall -g -ansi -save-temps -c main.c -o main.o
gcc.exe -o Sandbox.exe main.o  
main.c:6:9: warning: variable 'tab' set but not used [-Wunused-but-set-variable]
    6 |     int tab[i];
      |         ^~~
main.c:6:5: warning: 'i' is used uninitialized in this function [-Wuninitialized]
    6 |     int tab[i];
      |     ^~~
Output file is bin\Debug\Sandbox.exe with size 196.89 KB

Then:

int test(int i)
{
    int tab[i];
    tab[0] = 10;
    return 0;
}

Compiles too:

main.c: In function 'test':
main.c:5:9: warning: variable 'tab' set but not used [-Wunused-but-set-variable]
    5 |     int tab[i];
      |         ^~~
Output file is bin\Debug\Sandbox.exe with size 196.90 KB

Or:

int main()
{
    volatile int i;
    int tab[i];

    tab[0] = 10;

    return 0;
}

Only this is not compiling:

int main()
{
    // Comment
    return 0;
}
error: C++ style comments are not allowed in ISO C90

What am I missing? Thanks!


Solution

  • gcc has sloppy standard compliance per default. It defaults to lax C conformance + GNU extensions, equivalent to -std=gnu89 (current version defaults to -std=gnu17).

    When you type -ansi it does not mean conforming mode, but rather just the very same thing as -std=c89, "lax C89 mode". This compiler option may disable some GNU extensions... maybe... while keeping others. The difference between -std=c89 and -std=gnu89 is as poorly documented as the rest of gcc. We can read the unfriendly manual and it says:

    For example, -std=c90 turns off certain features of GCC that are incompatible with ISO C90, such as the asm and typeof keywords, but not other GNU extensions that do not have a meaning in ISO C90

    gcc supported variable-length arrays as an extensions even before C99, so switching out the GNU option ought to disable them, but not so... As far as I know, there is no official documentation over what features -std=c89 shuts off or at least I can't find it.

    What's important to realize is that -std=c89/-ansi alone does not push gcc into conforming mode! To do that, you need to do -std=c89 -pedantic or if you will -std=c89 -pedantic-errors. After which you'll get a diagnostic like this:

    error: ISO C90 forbids variable length array 'tab'

    And when compiling with these two options in combination, gcc probably has the best standard compliance of any compiler out there.