【问题标题】:Is GCC correct to warn of format string mismatch with a scoped enum?GCC 是否正确警告格式字符串与范围枚举不匹配?
【发布时间】:2017-02-08 09:10:16
【问题描述】:

在可变参数上下文中使用作用域枚举时,它被定义为作为其基础类型传递,如“Can I use enum class values as arguments to varargs functions?”中所回答的那样据我了解,这是唯一会转换作用域枚举的情况隐含地,就像一个无范围的枚举一样。

考虑这个程序:

enum Foo : char { F };
enum class Bar : char { B };

#include <cstdio>
int main()
{
    return !std::printf("%c\n", Foo::F)
        +  !std::printf("%c\n", Bar::B);
}

编译器(g++ 6.3.0 版)对Foo 的第一次打印很满意,但是当我通过Bar 时抱怨:

0.cpp: In function ‘int main()’:
0.cpp:10:34: warning: format ‘%c’ expects argument of type ‘int’, but argument 2 has type ‘Bar’ [-Wformat=]
         +  !printf("%c\n", Bar::B);
                                  ^

g++ 4.8.2 版没有抱怨这个,但g++ 6.3.0 有(这就是我现在担心的原因)。当存在实质性不匹配时,两个版本都会抱怨第一次打印,例如使用%f 或%s,或者如果我将Foo 更改为使用long 底层类型;这就是我启用-Wformat的原因。

我了解警告不是标准符合性问题,并且我知道如何更改我的代码来解决这些问题(例如,使用How can I output the value of an enum class in C++11? 的答案中的函数),但我也相信如果它们产生警告是无用的误报。当枚举的基础类型与格式字符串中的相应转换规范匹配时,将作用域枚举传递给格式化的 I/O 函数是否有任何潜在的实际危害?

【问题讨论】:

  • GCC 4.8 版可能没有抱怨,因为它没有完整的 C++11 实现,并且在 C++11 中引入了作用域枚举。
  • 从您链接的问题中查看接受的答案:无范围枚举值是整数提升,但范围枚举(enum class 的)不是。
  • @cpplearner 即使我将Bar 更改为enum class : int,它也会抱怨不匹配,所以这只是答案的一部分。
  • @Toby 不,不是:enum class 表示没有隐式转换为 int 或基础类型或其他类型的新类型,这些转换仍然适用于普通 enum。
  • @rubenvb,如果没有转换,那么这意味着只有在 va_arg() 调用使用完全相同的类型时才能使用通过 varargs 传递的作用域 int?我想我现在明白了。感谢所有评论和回答的人!

标签: c++ enums gcc-warning enum-class


【解决方案1】:

来自this scoped enumeration reference:

没有从范围枚举器的值到整数类型的隐式转换,...​​

[强调我的]

这意味着无论基类型如何,作用域枚举都不会隐式转换为int(或任何其他整数类型)。您必须明确地进行转换,例如static_cast(续上一段话):

...虽然static_cast可以用来获取枚举数的数值。


另外,来自this variadic argument reference:

bool、char、short 和 unscoped 枚举被转换为 int 或更宽的整数类型,如整数提升

[再次强调我的]


如果 GCC 正确地警告您,请回答您的问题:是的,它是正确的。你的做法不正确。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多