【问题标题】:Why does gcc throw an implicit-fallthrough warning?为什么 gcc 会引发隐式失败警告?
【发布时间】:2020-07-21 08:06:00
【问题描述】:

给定代码:

#include <stdlib.h> 

enum one {
    A, B
};

enum two {
    AA
};

int main(int argc, char *argv[])
{
    enum one one = atoi(argv[1]);
    enum two two = atoi(argv[2]);
    
    if ((one != A && one != B) || two != AA)
        return 1;
    
    switch (one) {
    case A:
        switch (two) {
        case AA:
            return 2;
        }
    case B:
        return 3;
    }
    return 0;
}

当我使用 gcc -Wimplicit-fallthrough test_fallthrough.c 编译它时,我收到以下警告

test_fallthrough.c: In function 'main':
test_fallthrough.c:21:3: warning: this statement may fall through [-Wimplicit-fallthrough=]
   21 |   switch (two) {
      |   ^~~~~~
test_fallthrough.c:25:2: note: here
   25 |  case B:
      |  ^~~~

它试图警告什么,我可以做些什么使它不警告(我宁愿避免添加诸如/* Falls through. */之类的cmets)

【问题讨论】:

  • I would prefer to avoid adding comments such as /* Falls through. */ what can I do so that it does not warn ?使用该评论。

标签: c gcc gcc-warning


【解决方案1】:

您在第一个 switch 语句中缺少break,它可能会落入第二种情况,它可以执行case A,然后执行Case B,因此会出现警告。

//...
switch (one)
{
case A:
    switch (two)
    {
    case AA:
        return 2;
    }
    break; //breaking case A removes the warning.
case B:
    return 3;
}
//...

旁注:

  • 使用argc 检查argv[1]argv[2] 是否存在总是一个好主意。

【讨论】:

  • 看起来clang能够确定内部开关永远不会允许流继续,所以它不会发出警告,但是gcc无法注意到,所以它需要中断知道
  • @finks,根据我的经验,clang 通常比 gcc“更聪明”。
【解决方案2】:

通常,编译器会在每个case 主体之后检查break 语句,以确保程序流(失败)没有错误。

在您的情况下,case A 正文没有break,当switch 语句与case A 的语句匹配时,也让case B 继续执行。

switch (one) {
    case A:
        switch (two) {
        case AA:
            return 2;
        }
         // <------ no break here, flow will continue, or fall-through to next case body
    case B:
        return 3;
    }
    return 0;
}

【讨论】:

    【解决方案3】:

    为什么 gcc 会抛出隐式失败警告?

    好吧,因为它可能会失败。

    它试图警告什么

    two != AA 时从case A 变为case B

    我该怎么做才能让它不发出警告

    在低于 7 的 gcc 上使用注释,即。 one of the markers that disable the warning:

    /* falls through */
    

    在 gcc 7 以上你可以use a attribute:

    __attribute__((__fallthrough__));
    

    在 10 以上的 gcc 上,您可以使用 the attribute from C2x:

    [[fallthrough]];
    

    --

    请注意,if (one != A || one != B || two != AA) 并没有真正检查任何内容,因为one != A || one != B 将始终为真。我猜你打算像if ((one != A &amp;&amp; one != B) || two != AA) 那样做。无论如何,-Wimplicit-falthrough= 警告仍然没有考虑到if

    【讨论】:

      猜你喜欢
      • 2011-12-05
      • 2021-12-27
      • 1970-01-01
      • 2018-07-26
      • 1970-01-01
      • 2014-01-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多