C++ 使用int和移位执行逐位和
这个问题基于: 问题的根源是-我定义了一个C++ 使用int和移位执行逐位和,c++,bit,shift,negative-number,C++,Bit,Shift,Negative Number,这个问题基于: 问题的根源是-我定义了一个enum,它表示不同的掩码。 并且需要使用enum(掩码)对变量进行和,然后将结果右移。 由于enum类型始终为int,因此该变量也被定义为int。但正如您所见,右移负数时出现问题。 如何解决这个问题呢?您可以先移位,然后逆移位掩码来解决这个问题。您可以先移位,然后逆移位掩码来解决这个问题。我建议您在移位之前将枚举的值静态强制转换为unsigned long。我认为这是您可以使用的最安全的选项。我建议您在移位之前将枚举的值静态强制转换为unsigned
enum
,它表示不同的掩码。
并且需要使用enum
(掩码)对变量进行和,然后将结果右移。
由于enum
类型始终为int
,因此该变量也被定义为int
。但正如您所见,右移负数时出现问题。
如何解决这个问题呢?您可以先移位,然后逆移位掩码来解决这个问题。您可以先移位,然后逆移位掩码来解决这个问题。我建议您在移位之前将枚举的值静态强制转换为unsigned long
。我认为这是您可以使用的最安全的选项。我建议您在移位之前将枚举的值静态强制转换为unsigned long
。我认为这是您可以使用的最安全的选项。首先,enum
类型并不总是int
;在C++11中,您可以
甚至强制它为无符号类型。第二,即使
基础类型是int
,您可以(也应该)自由转换为
从未签名的
,没有真正的风险。例如,您可以过载
操作符&
因此:
MyEnum
operator&( MyEnum lhs, MyEnum rhs )
{
return static_cast<MyEnum>(
static_cast<unsigned>( lhs) & static_cast<unsigned>( rhs ) );
}
MyEnum
运算符&(MyEnum lhs、MyEnum rhs)
{
返回静态输出(
静态_-cast(左侧)和静态_-cast(右侧));
}
提取可能位于某个中间位置的字段:
int
getFieldX( MyEnum values )
{
return static_cast<unsigned>(values & fieldXMask) >> fieldXOffset;
}
int
getFieldX(MyEnum值)
{
返回静态_cast(值和fieldXMask)>>fieldXOffset;
}
这将确保行为正确(并且一旦未签名的值
已移位,应转换为int
,而不会丢失
首先,enum
类型并不总是int
;在C++11中,您可以
甚至强制它为无符号类型。第二,即使
基础类型是int
,您可以(也应该)自由转换为
从未签名的
,没有真正的风险。例如,您可以过载
操作符&
因此:
MyEnum
operator&( MyEnum lhs, MyEnum rhs )
{
return static_cast<MyEnum>(
static_cast<unsigned>( lhs) & static_cast<unsigned>( rhs ) );
}
MyEnum
运算符&(MyEnum lhs、MyEnum rhs)
{
返回静态输出(
静态_-cast(左侧)和静态_-cast(右侧));
}
提取可能位于某个中间位置的字段:
int
getFieldX( MyEnum values )
{
return static_cast<unsigned>(values & fieldXMask) >> fieldXOffset;
}
int
getFieldX(MyEnum值)
{
返回静态_cast(值和fieldXMask)>>fieldXOffset;
}
这将确保行为正确(并且一旦未签名的值
已移位,应转换为int
,而不会丢失
值)。为什么不能将变量定义为uint64\u t
?我想他想移动枚举值。@IvayloStrandjev-我想在和之后移动结果。您可以使枚举的基础类型不同。@AlexChamberlain-我定义它为int64\t,以便与int(枚举掩码)一致为什么您不能将变量定义为uint64\t
?我想他想移动枚举值。@IvayloStrandjev-我想在和之后移动结果。您可以使枚举的基础类型不同。@AlexChamberlain-我定义它为int64\t以与int(枚举掩码)一致,这是最安全的,但如果计算机硬件不支持64位类型,并且您的枚举不需要64位类型,则可能会对性能造成重大影响。对于各种“重要”值,这是最安全的,但如果计算机硬件不支持64位类型,则可能会对性能造成重大影响,您的枚举不需要它们。对于各种“重要”值。@Yackov我也不需要。我已经使用上面的代码超过20年了。(如果你真的想稳妥行事,至少可以选择uint\u t
,而不是unsigned
。但对于大多数情况来说,unsigned
就足够了。)@Yackov我也不这么认为。我已经使用上面的代码超过20年了。(如果你真的想稳妥起见,请至少转换为uint\u t
,而不是unsigned
。但在大多数情况下,unsigned
就足够了。)