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

Time:10-11

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!

CodePudding user response:

Variable length array is a GCC extension in older standard versions. Extensions are "compatible" with the standard. If you want to exactly adhere to the standard, i.e. you want to get a message when using an extension, add -pedantic option (and -pedantic-errors for errors).

Gcc docs: https://gcc.gnu.org/onlinedocs/gcc-12.2.0/gcc/Variable-Length.html#Variable-Length , https://gcc.gnu.org/onlinedocs/gcc-12.2.0/gcc/Warning-Options.html#Warning-Options .

CodePudding user response:

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.

  • Related