GCC 是否正确警告格式字符串与作用域枚举不匹配?
Is GCC correct to warn of format string mismatch with a scoped enum?
当在 varargs 上下文中使用范围枚举时,它被定义为作为其基础类型传递,如“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 函数是否存在潜在的实际危害?
来自 this scoped enumeration reference:
There are no implicit conversions from the values of a scoped enumerator to integral types, ...
[强调我的]
这意味着无论基类型如何,作用域枚举都不会隐式转换为 int
(或任何其他整数类型)。您必须明确地进行转换,例如static_cast
(接上一引):
... although static_cast
may be used to obtain the numeric value of the enumerator.
此外,来自 this variadic argument reference:
bool
, char
, short
, and unscoped enumerations are converted to int
or wider integer types as in integer promotion
[再次强调我的]
并回答你的问题,如果 GCC 警告你是正确的:是的,它是正确的。你这样做是不正确的。
当在 varargs 上下文中使用范围枚举时,它被定义为作为其基础类型传递,如“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 函数是否存在潜在的实际危害?
来自 this scoped enumeration reference:
There are no implicit conversions from the values of a scoped enumerator to integral types, ...
[强调我的]
这意味着无论基类型如何,作用域枚举都不会隐式转换为 int
(或任何其他整数类型)。您必须明确地进行转换,例如static_cast
(接上一引):
... although
static_cast
may be used to obtain the numeric value of the enumerator.
此外,来自 this variadic argument reference:
bool
,char
,short
, and unscoped enumerations are converted toint
or wider integer types as in integer promotion
[再次强调我的]
并回答你的问题,如果 GCC 警告你是正确的:是的,它是正确的。你这样做是不正确的。