为什么GCC警告我这一行“缩进得像是由”if“保护”的一样具有误导性呢?

16

警告如下:

/home/dronz/OF/apps/myApps/HexMap/src/HexMap.cpp:48:5: warning:
this ‘if’ clause does not guard... [-Wmisleading-indentation]

     if (toHexSize < 1)
     ^~

/home/dronz/OF/apps/myApps/HexMap/src/HexMap.cpp:51:2: note: ...
this statement, but the latter is misleadingly indented as
if it were guarded by the ‘if’

  MapTileSizeAtZoom = toHexSize;
  ^~~~~~~~~~~~~~~~~

代码如下:

if (toHexSize < 1)
    toHexSize = 1;

MapTileSizeAtZoom = toHexSize;

如果 MapTileSizeAtZoom ... 那一行的缩进更深,我认为可能会有误导性,但是它与 'if' 在同一层级缩进,所以对我来说看起来是正确的。

我想也许存在额外的空格和/或制表符,但是我删除了文本后面的任何不必要的空白字符,但没有什么改变。

我想也许是由于空行的原因导致警告,但是将其删除并没有停止警告。

此外,在同一个 .cpp 文件中,在它之前有这段代码,但它没有发出警告:

if (toHexSize < 1)
    toHexSize = 1;

HexInfo centerOnHex;
if (SelectedHex.type != -1)

为什么它会警告其中一个(总之),却不警告另一个,不管这是否是GCC的错误,我该怎么避免它呢?

代码

#include "HexMap.h"
#include <algorithm>
#include <cmath>

//--------------------------------------------------------------
HexMap::HexMap()
{}

//--------------------------------------------------------------
int HexMap::SetZoom(int toHexSize)
{
    if (toHexSize < 1)
        toHexSize = 1;

    HexInfo centerOnHex;
    if (SelectedHex.type != -1)
    {
        // Center map on the selected hex.
        centerOnHex = SelectedHex;
    }
    else
    {
        // Center map on current center of viewpoint.
        centerOnHex = GetHex(
            MapFrame.x + MapFrame.getWidth() / 2,
            MapFrame.y + MapFrame.getHeight() / 2 );
        if ((centerOnHex.x > WORLDMAPWIDTH) || (centerOnHex.x < 0))
            centerOnHex.x = WORLDMAPWIDTH / 2;
        if ((centerOnHex.y > WORLDMAPHEIGHT) || (centerOnHex.y < 0))
            centerOnHex.y = WORLDMAPHEIGHT / 2;
    }

    setHexDisplaySize(toHexSize);

    // Center map:
    HexOriginX = MapFrame.x + MapTileWidth  * 0.25f;
    HexOriginY = MapFrame.y + MapTileHeight * 0.5f;
    ViewPosOnWorld.set(
        centerOnHex.x - (MapFrame.getWidth() / 2) / MapTileWidth,
        centerOnHex.y - (MapFrame.getHeight() / 2) / MapTileHeight);

    return 0;
}

//--------------------------------------------------------------
void HexMap::setHexDisplaySize(int toHexSize)
{
    if (toHexSize < 1)
        toHexSize = 1;

    MapTileSizeAtZoom = toHexSize;
    MapTileWidth = MapTileSizeAtZoom * 1.5f; // hex x-spacing is 1.5 * r
    MapTileHeight = MapTileSizeAtZoom * 1.73205f; // hex height = sqrt(3*r)

    // Size images & hexmask:
    MaskWidth = MapTileHeight * 1.154700538;  // 1/(sqrt(3)/2)
}

1
对我来说,这是一个相当不寻常和令人惊讶的错误。为什么gcc会关注缩进呢?我以为C++是自由格式的。 - Gaurav Singh
发布所有的代码。 - user2100815
8
@G_S它试图帮助你避免因忘记使用“{}”等符号而犯下愚蠢的错误。请参阅https://gcc.gnu.org/git/?p=gcc.git;a=blobdiff;f=gcc/doc/invoke.texi;h=117b5d99dfc7ad2c60225c21c4f8d65f726695fc;hp=b5721c9f242dc01efe895f49b55e3977809d46b8;hb=e5f01cbafce70120afe8f73df099dcc2796adcd7;hpb=5c5c1f00cfc6fb2f2e6e3721629ee0391a9a95b4 - Jesper Juhl
1
MISRA标准建议即使是单行语句也要使用{}括号以避免此类问题。https://rules.sonarsource.com/c/RSPEC-3807 - Makesh
1
@Makesh:是的,地球上几乎所有花括号语言的编码标准都有这个建议。相关链接:*从苹果的#gotofail安全漏洞中学习* - “坚持使用花括号会更加突出错误”。 - Peter Mortensen
2个回答

48

第49行的条件语句使用了空格缩进,但第51行使用的是制表符

GCC将制表符视为8个空格。编译器错误地认为它与if语句对齐,即使在编辑器中看起来并非如此。这是保持空白缩进一致性的另一个原因(例如,避免在源代码中使用任何制表符)。


4
使用像clang-format这样的格式化工具是避免未来出现问题并在代码库中强制执行代码风格一致性的好方法。 - eozd
3
通过在if语句中始终使用大括号,除非整个if语句在单行上,可以避免这个问题。养成这个习惯将会在未来为您节省痛苦,当您添加第二个语句到if块并忘记添加大括号时。 - Alan Birtles
2
在大多数IDE上,您还可以设置选项卡以转换为空格。我在主机上编写的最早的脚本之一是rogstop,它将COBOL的缩进与句点位置进行比较(没有大括号,它们太复杂了,所以一个块只是没有在末尾加上句点的代码行。是的,这个脚本找到了许多缺少最后一行句点或部分有额外句点的错误)。 - Mike
3
选项 *-Wmisleading-indentation*:此选项指示 GCC 在出现可能会导致代码含义混淆的缩进时生成警告。例如,如果使用不一致的缩进来表示块结构,则此选项将生成警告。 - Peter Mortensen
2
更改选项,例如更合理的4个空格,是-ftabstop - Peter Mortensen
显示剩余3条评论

2

使用大括号 {}:

if(x == y) {
    x = x + 1;
}

这应该可以解决代码中任何缩进问题,从而解决该问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接