为什么存储在位场中的枚举类的static_cast会更改结果?
给定一个enum类
存储在一个位置:
#include <cstdint>
#include <iostream>
enum class Orientation: uint8_t
{
NORMAL = 0,
CLOCKWISE = 1,
ANTICLOCKWISE = 2
};
inline Orientation operator+(const Orientation& lvalue, const Orientation& rvalue)
{
switch(lvalue)
{
case Orientation::NORMAL: return rvalue;
case Orientation::CLOCKWISE:
switch (rvalue)
{
case Orientation::CLOCKWISE: return Orientation::ANTICLOCKWISE;
case Orientation::ANTICLOCKWISE: return Orientation::NORMAL;
case Orientation::NORMAL: return Orientation::CLOCKWISE;
}
__builtin_unreachable();
case Orientation::ANTICLOCKWISE:
switch (rvalue)
{
case Orientation::CLOCKWISE: return Orientation::NORMAL;
case Orientation::ANTICLOCKWISE: return Orientation::CLOCKWISE;
case Orientation::NORMAL: return Orientation::ANTICLOCKWISE;
}
__builtin_unreachable();
}
__builtin_unreachable();
}
class Puzzle {
private:
Orientation or1_ : 2;
Orientation or2_ : 2;
public:
Puzzle(
const Orientation or1,
const Orientation or2
) :
or1_(or1),
or2_(or2)
{}
bool checkPolarity() const
{
return (or1_ + or2_)
== Orientation::NORMAL;
}
bool checkPolarityWithCast() const
{
return (static_cast<Orientation>(or1_) + static_cast<Orientation>(or2_))
== Orientation::NORMAL;
}
};
int main()
{
Puzzle puzzle(
Orientation::ANTICLOCKWISE,
Orientation::CLOCKWISE
);
std::cout << "No cast: " << puzzle.checkPolarity() << '\n';
std::cout << "Cast: " << puzzle.checkPolarityWithCast() << '\n';
}
在X86-64 GCC 8.4、8.5、9.3、9.4和9.5中,输出为:
否铸造:0 演员:1
但是从GCC 10来看,输出为:
否铸造:1 演员:1
为什么static_cast
对输出有所不同?是从G ++ 10固定的编译器中的错误吗?
godbolt
Given an enum class
stored in a bit-field:
#include <cstdint>
#include <iostream>
enum class Orientation: uint8_t
{
NORMAL = 0,
CLOCKWISE = 1,
ANTICLOCKWISE = 2
};
inline Orientation operator+(const Orientation& lvalue, const Orientation& rvalue)
{
switch(lvalue)
{
case Orientation::NORMAL: return rvalue;
case Orientation::CLOCKWISE:
switch (rvalue)
{
case Orientation::CLOCKWISE: return Orientation::ANTICLOCKWISE;
case Orientation::ANTICLOCKWISE: return Orientation::NORMAL;
case Orientation::NORMAL: return Orientation::CLOCKWISE;
}
__builtin_unreachable();
case Orientation::ANTICLOCKWISE:
switch (rvalue)
{
case Orientation::CLOCKWISE: return Orientation::NORMAL;
case Orientation::ANTICLOCKWISE: return Orientation::CLOCKWISE;
case Orientation::NORMAL: return Orientation::ANTICLOCKWISE;
}
__builtin_unreachable();
}
__builtin_unreachable();
}
class Puzzle {
private:
Orientation or1_ : 2;
Orientation or2_ : 2;
public:
Puzzle(
const Orientation or1,
const Orientation or2
) :
or1_(or1),
or2_(or2)
{}
bool checkPolarity() const
{
return (or1_ + or2_)
== Orientation::NORMAL;
}
bool checkPolarityWithCast() const
{
return (static_cast<Orientation>(or1_) + static_cast<Orientation>(or2_))
== Orientation::NORMAL;
}
};
int main()
{
Puzzle puzzle(
Orientation::ANTICLOCKWISE,
Orientation::CLOCKWISE
);
std::cout << "No cast: " << puzzle.checkPolarity() << '\n';
std::cout << "Cast: " << puzzle.checkPolarityWithCast() << '\n';
}
In x86-64 gcc 8.4, 8.5, 9.3, 9.4 and 9.5 the output is:
No cast: 0 Cast: 1
But from gcc 10, the output is:
No cast: 1 Cast: 1
Why does the static_cast
make a difference to the output? Is it a bug in the compiler that was fixed from g++ 10?
godbolt here
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
With G++8.4, the assembly code for
Puzzle.checkPolarity()
is:And, as
如由yksisarvinen评论
但是,该错误报告指出:
而且看来它还没有完全固定,因为它似乎仍在X86-64 GCC 8.4、8.5、9.3、9.4和9.5中被错误,但该修复程序似乎确实从版本10中使用了。
With G++8.4, the assembly code for
Puzzle.checkPolarity()
is:And, as commented by Goswin von Brederlow
As commented by Yksisarvinen
However, that bug report states:
and it appears that it has not entirely been fixed as it is still appearing to be bugged in x86-64 gcc 8.4, 8.5, 9.3, 9.4 and 9.5 but the fix does appear to have worked from version 10.