【发布时间】:2016-11-21 13:47:47
【问题描述】:
tl;dr 在进行整数提升时,位操作是否安全且行为符合预期(类型短于int)?
例如
uint8_t a, b, c;
a = b & ~c;
这是我所拥有的粗略的 MCVE:
struct X { // this is actually templated
using U = unsigned; // U is actually a dependent name and can change
U value;
};
template <bool B> auto foo(X x1, X x2) -> X
{
if (B)
return {x1.value | x2.value};
else
return {x1.value & ~x2.value};
}
这很好用,但是当U 更改为比int 短的整数类型时,例如std::uint8_t 然后由于整数促销,我收到警告:
警告:缩小 '(int)(((unsigned char)((int)x1.X::value)) | ((unsigned char)((int)x2.X::value)))' 来自 'int' to 'X::U {aka unsigned char}' inside {} [-Wnarrowing]
所以我加了一个static_cast:
struct X {
using U = std::uint8_t;
U value;
};
template <bool B> auto foo(X x1, X x2) -> X
{
if (B)
return {static_cast<X::U>(x1.value | x2.value)};
else
return {static_cast<X::U>(x1.value & ~x2.value)};
}
问题:整数提升和缩小转换是否会与预期结果 (*) 混淆?尤其是因为这些是来回转换符号(unsigned char -> int -> unsigned char)。如果U 已签名,即std::int8_t 会怎样(它不会在我的代码中签名,但如果是的话,我会好奇这种行为)。
我的常识认为代码完全没问题,但我的 C++ 偏执狂认为至少有可能实现定义的行为。
(*) 如果不清楚(或者我搞砸了),预期的行为是设置或清除位(x1 是值,x2 是掩码,B 是设置/清除操作)
【问题讨论】:
标签: c++ bit-manipulation integer-promotion