简体   繁体   English

GCC 选项 -Wdeclaration-after-statement 纯粹是风格化的吗?

[英]Is the GCC option -Wdeclaration-after-statement purely stylistic?

Is the option -Wdeclaration-after-statement stylistic only?选项-Wdeclaration-after-statement仅适用-Wdeclaration-after-statement样式? 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?我的意思是,如果我对 C 代码中定义了变量的所有情况进行宏处理,并以相同的方式在其中初始化它们,从这种较旧的 C90 样式迁移到较新的 C99 样式,那么该代码会是字节吗? -byte一样吗?

Here is how the option -Wdeclaration-after-statement is documented (from man gcc ):以下是选项-Wdeclaration-after-statement的记录方式(来自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.这个结构,从 C++ 中知道,是在 ISO C99 中引入的,默认情况下在 GCC 中是允许的。 It is not supported by ISO C90. 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 .这是我在这里提出的问题后续行动

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.在 C99 之前,所有变量声明都必须发生块中的任何语句之前 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:在 C 中不能做但在 C++ 中一直完全合法的是混合声明和语句:

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.随着 C99 的出现,您现在可以在 C 中做与在 C++ 中相同的事情,并在块中的任何地方声明一个变量,即使在非声明语句之后也是如此。

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).编译器现在有点复杂(而且更大)。

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.这些术语取自正式的 C 语法。

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.您的两个示例与此 gcc 设置无关,因此您似乎误解了它的作用。

Rather, the relevant example would be:相反,相关的例子是:

{
    int a = 42;
}

versus相对

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

The former example is fine in any C version.前一个例子适用于任何 C 版本。 The latter is fine in standard C, but not in the deprecated C90 standard.后者在标准 C 中很好,但在已弃用的 C90 标准中则不然。 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.因此,现在警告的唯一目的是为强制执行某种编码风格的标准 C 程序提供诊断消息。

The vast majority of programmers out there should not use this warning and stick to standard C as defined in ISO 9899:2018.绝大多数程序员不应该使用此警告并坚持 ISO 9899:2018 中定义的标准 C。

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 .下面的foobarbaz不会 Here is a link to GodBolt .这是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 );
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM