错误:这个语句可能会失败 [-Werror=implicit-fallthrough=]

问题描述 投票:0回答:5

我试图在 ubuntu 上编译 mitk,但我得到了这个错误:

error:这个语句可能会通过 [-Werror=implicit-fallthrough=]

这里有一部分代码:

      /** Get memory offset for a given image index */
      unsigned int GetOffset(const IndexType & idx) const
      {
       const unsigned int * imageDims = m_ImageDataItem->m_Dimensions;

        unsigned int offset = 0;
        switch(VDimension)
        {
        case 4:
         offset = offset + idx[3]*imageDims[0]*imageDims[1]*imageDims[2];
        case 3:
        offset = offset + idx[2]*imageDims[0]*imageDims[1];
        case 2:
        offset  = offset + idx[0] + idx[1]*imageDims[0];
         break;
        }

        return offset;
      }

如有任何帮助,我将不胜感激。

c++ gcc build gcc-warning mitk
5个回答
14
投票

Switch case 语句默认会失效。在所示程序的情况下,如果

VDimension
是 4 那么所有

offset = offset + idx[3]*imageDims[0]*imageDims[1]*imageDims[2];
offset = offset + idx[2]*imageDims[0]*imageDims[1];
offset  = offset + idx[0] + idx[1]*imageDims[0];

将被执行。

其他一些语言,比如Pascal,只执行一个case,没有fall through的概念。因此,刚接触 C++ 的程序员可能会无意中编写 fall through switches。

如果掉线是无意的,您需要在每个案例之间添加一个中断以防止掉线。

这个声明可能落空

此警告通知程序员有关失败的信息。可以使用 GCC 编译器开关

-Wimplicit-fallthrough
控制此警告选项。默认不开启,也不是
-Wall
开启,而是
-Wextra
开启。

如果使用

-Werror
开关,警告会变成错误。
-Werror
默认情况下未启用。

C++17 引入了

[[fallthrough]]
属性,该属性可用于在有意时明确记录失败。如果使用它,编译器不应发出警告:

        switch(VDimension)
        {
        case 4:
         offset = offset + idx[3]*imageDims[0]*imageDims[1]*imageDims[2];
         [[fallthrough]];
        case 3:
         offset = offset + idx[2]*imageDims[0]*imageDims[1];
         [[fallthrough]];
        case 2:
         offset = offset + idx[0] + idx[1]*imageDims[0];
         break;
        }

在C++17之前,GCC提供了一个语言扩展属性

__attribute__ ((fallthrough))
,目的相同。

失败也可以用注释记录下来,

Wimplicit-fallthrough
可以根据开关使用的值检测到这样的注释。 GCC 文档中的更多详细信息。


6
投票

您应该在每个 case 语句中添加关键字 break,如果您不这样做,代码将从匹配条件的 case 运行并继续满足

休息;

例如:如果 VDimension = 4,则代码将从案例 4 运行 => 继续到案例 3 => 继续到案例 2 然后中断。这意味着它将执行以下命令:

offset = offset + idx[3]*imageDims[0]*imageDims[1]*imageDims[2];
offset = offset + idx[2]*imageDims[0]*imageDims[1];
offset  = offset + idx[0] + idx[1]*imageDims[0];
break;
return offset;

我认为你的代码应该是:

/** Get memory offset for a given image index */
  unsigned int GetOffset(const IndexType & idx) const
  {
   const unsigned int * imageDims = m_ImageDataItem->m_Dimensions;

    unsigned int offset = 0;
    switch(VDimension)
    {
    case 4:
     offset = offset + idx[3]*imageDims[0]*imageDims[1]*imageDims[2];
     break;
    case 3:
     offset = offset + idx[2]*imageDims[0]*imageDims[1];
     break;
    case 2:
     offset  = offset + idx[0] + idx[1]*imageDims[0];
     break;
    }

    return offset;
  }

3
投票

如果您绝对确定警告无关紧要,请在编译期间删除

-Werror
标志。

对于在配置阶段放置标志的项目,您可以这样做

./configure --disable-werror

跑步前

make


0
投票

假设代码是正确的,如果可以的话,只需将

-Wno-implicit-fallthrough
添加到编译器标志。这在 Makefile 中通常是
CFLAGS
CXXFLAGS

正如其他人所说,当 VDimension 为 4 时,案例 4、3 和 2 的代码将按该顺序执行,因为没有

break
语句来阻止它。如果那是预期的行为(我怀疑是),那么编译器会烦人地警告你 switch 语句正在做它应该做的事情。


0
投票
      /** Get memory offset for a given image index */
  unsigned int GetOffset(const IndexType & idx) const
  {
   const unsigned int * imageDims = m_ImageDataItem->m_Dimensions;

    unsigned int offset = 0;
    switch(VDimension)
    {
    case 4:
     offset = offset + idx[3]*imageDims[0]*imageDims[1]*imageDims[2];
     break;
    case 3:
    offset = offset + idx[2]*imageDims[0]*imageDims[1];
     break;
    case 2:
    offset  = offset + idx[0] + idx[1]*imageDims[0];
     break;
    }

    return offset;
  }

只需添加“中断;”完成任何案件后。

© www.soinside.com 2019 - 2024. All rights reserved.