Home > other >  Is the GCC option -Wdeclaration-after-statement purely stylistic?
Is the GCC option -Wdeclaration-after-statement purely stylistic?

Time:10-30

Is the option -Wdeclaration-after-statement stylistic only? By that I mean, if I macro'd all cases in my C code where a variable was defined and I initialized them in them in the same fashion migrating from this older style C90 to the newer C99 style, would that code be byte-for-byte the same?

Here is how the option -Wdeclaration-after-statement is documented (from man gcc):

Warn when a declaration is found after a statement in a block. This construct, known from C , was introduced with ISO C99 and is by default allowed in GCC. It is not supported by ISO C90.

And it allows you to take code like

int a;
{
    a = 42;
    printf( "%d", a );
}

and turn it into

int a = 42;
printf( "%d", a );

This is a follow-up to my question here.

CodePudding user response:

I may be confused here, but I think that we are missing something.

Prior to C99, all variable declarations had to occur before any statements in a block. It did not matter where you assigned it a value (except maybe in generated assembly code).

int a;
do_something();
a = 7;
do_something_else();

What you could not do in C but has always been perfectly legal in C is mix declarations and statements:

do_something();
int a = 7;
do_something_else();

With the advent of C99 you can now do the same thing in C as you can in C , and declare a variable anywhere in a block, even after non-declaration statements.

Ultimately it was a design decision based on making it easier to write a compiler that leaked into the language specification. Compilers are a little more sophisticated now (and much larger).

CodePudding user response:

Statement in this context either refers to a full expression ending with ; or alternatively a compound statement, { }. These terms are taken from the formal C grammar.

Declaration after statement does not apply to the code in your question. Because... you placed the declaration before a (compound) statement. Your two examples have nothing to do with this gcc setting, so it would appear that you have misunderstood what it does.

Rather, the relevant example would be:

{
    int a = 42;
}

versus

{
  puts("hello");
  int a = 42;
}

The former example is fine in any C version. The latter is fine in standard C, but not in the deprecated C90 standard. So the only purpose of the warning nowadays would be to give a diagnostic message for standard C programs where a certain coding style is enforced.

The vast majority of programmers out there should not use this warning and stick to standard C as defined in ISO 9899:2018.

CodePudding user response:

No, it's not. For example, the above two snippets will compile byte-for-byte the same. So will the foo and bar below, but baz will not. Here is a link to GodBolt. This demonstrates that hoisting the initialization to the declaration may NOT produce the same code

void foo () {
    int a;
    {
        if ( 1 ) {
            a = 42;
            printf( "%d", a );
        }
        else {
            a = 42;
            printf( "%d", a );
        }
    }
}

void bar () {
    int a = 42;
    {
        if ( 1 ) {
            printf( "%d", a );
        }
        else {
            printf( "%d", a );
        }
    }
}

void baz () {
    int a;
    {
        if ( rand() > 0 ) {
            a = 42;
            printf( "%d", a );
        }
        else {
            a = 42;
            printf( "%d", a );
        }
    }
}
  • Related