【问题标题】:G++ Unused Label Warning for Preprocessor Macro预处理器宏的 G++ 未使用标签警告
【发布时间】:2021-07-29 02:16:48
【问题描述】:

我正在处理项目中的编译器警告,试图清理代码,一个令我困惑的警告/错误是以下代码的unused-label 警告。

STATE(initialize)

它表示“初始化”标签已定义但未使用。 STATE 是一个#define 宏,如下:

#define STATE(x)    x: __TRACE__("enter", #x);

__TRACE__宏如下:

#define __TRACE__(y,x) dbg.printf(DebugIO::debug2,"FSM:" y "(" x ")\n");

请注意,我没有编写此代码,只是在完成一个项目,试图尽可能多地纠正警告。但据我所知,initialize 标签被传递给__TRACE__,它被用作printf() 调用的参数。

那么,为什么不使用它呢?编译器是否不会查看预处理器指令以了解变量的使用情况?

我该如何纠正这个问题?

【问题讨论】:

    标签: c++


    【解决方案1】:

    据我所知,initialize 标签被传递给__TRACE__,它被用作printf() 调用的参数。

    不,实际上不是。 STATE()x参数与__TRACE__()x参数不同。

    STATE(initialize)语句中,x参数是initialize,所以x:变成了简单的initialize:(有问题的标签),但是#xx的输入值字符串化为@在本例中为 987654335@,因此 STATE(initialize) 扩展为:

    initialize: __TRACE__("enter", "initialize");
    

    然后,在__TRACE__ 宏中,y 参数为"enter"x 参数为"initialize",所以__TRACE__("enter", "initialize") 扩展为:

    dbg.printf(DebugIO::debug2,"FSM:" "enter" "(" "initialize" ")\n");
    

    最后,仅由空格分隔的字符串文字由编译器合并在一起,因此STATE(initialize) 的最终代码如下所示:

    initialize: dbg.printf(DebugIO::debug2,"FSM:enter(initialize)\n");;
    

    由于没有 goto 或其他引用 initialize 标签的语句,这就是您收到警告的原因。

    我该如何纠正这个问题?

    除非代码中某处有实际的 goto initialize 语句,否则我会完全去掉标签:

    #define STATE(x)    __TRACE__("enter", #x);
    

    【讨论】:

    • 啊,我想知道 # 运算符在这种情况下做了什么,因为我不经常使用预处理器指令。谢谢你的解释。
    • 仔细检查后,在 STATE() 调用之前有一个 GOTO,它在初始化标签上调用 goto。不确定这是否会破坏事情。
    • 那么,在这种情况下,标签就不会被使用,编译器也不应该抱怨它。听起来像一个编译器错误。
    • 无论如何,我问了我团队的一位高级成员,他们说不要触摸 FSM 代码,只需取消警告即可。
    【解决方案2】:

    警告的真正原因是

    x: TRACE...
    

    介绍与goto 一起使用的标签。可以理解,没有 goto 来初始化状态(看起来我们正在查看 FSM 实现)。

    如果不重新构建框架,可能无法删除此警告(例如,添加一个特殊的状态宏,它不会为您从未进入的状态定义标签),但也可以只关闭此特定警告项目。

    【讨论】:

    • 是的,它是一个 FSM 实现,是的,在 STATE 之前有一个 GOTO 调用,它引用了初始化标签。有没有一种方法可以在不抑制其他实例的情况下仅抑制“未使用标签”的这个实例?
    【解决方案3】:

    注意__attribute__((unused))可以用on a label

    将宏参数转换为字符串不能算作“使用”恰好具有相同名称的标签(请记住,标签无论如何都是独立于变量的命名空间,更不用说宏参数了)。

    使用(GCC 扩展)一元 && 运算符来获取标签的地址也可能会抑制警告,但通常你应该避免任何看起来像动态 goto 的东西,除非你真的知道你的重新做。所以更喜欢属性版本。


    还要注意__TRACE__ 是一个保留名称,因为它包含两个相邻的下划线。

    【讨论】:

    • 也可以使用[[maybe_unused]]。 MSVC 出于某种原因不接受它,但 GCC 和 Clang 可以。
    猜你喜欢
    • 2016-04-30
    • 2016-09-02
    • 2021-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-15
    相关资源
    最近更新 更多