【问题标题】:Is it possible to specify return types from bitwise manipulation?是否可以通过按位操作指定返回类型?
【发布时间】:2019-05-06 07:39:47
【问题描述】:

在我工作的公司中,很多代码经常使用 unsigned char 类型来处理小数字,以避免在数据结构中出现不必要的填充。我很少看到这个问题,但是我在使用位运算符设置错误标志时遇到了一个隐式转换的小问题。我通过简单地明确找到了一种解决方法,但我想知道是否有更优雅的方法。顺便说一句,我们用 c++11 编译

鉴于下面的错误代码枚举:

enum ErrorType : unsigned char
{
    OK.     = 0x00,
    ERROR01 = 0x01,
    ERROR02 = 0x02
};

并假设我有一些带有 errorType 类型的私有成员的类 这将使用公共成员来设置或取消设置标志,例如:

struct S
{
public:
void setError1();
void unsetError1();

private:
ErrorType errorType;
};

如果我尝试在下面隐式设置值:

void S::setError1()
{
    this->errorType |= ERROR01;
}

我收到类型转换错误

但是,如果我明确地转换按位转换,它就可以工作

this->errorType = ErrorType(this->errorType | ERROR01);

问题似乎在于按位转换的输出始终是整数,不一定反映输入类型。这是真的?如果是这样,有没有办法为它指定一个类型,这样我就不必每次都显式地强制转换?

【问题讨论】:

  • enum ErrorType : unsigned char - 你可能想要enum class 那里..
  • 创建自己的ErrorType& operator|=(ErrorType& a, ErrorType b);
  • @JesperJuhl 不一定,虽然
  • 注意:标准中没有对charshort的操作。所有操作员至少在int 上工作。因此char在操作前被转换为int。运算结果与输入参数相同(转换后)。请参阅:Implicit type conversion rules in C++ operators 注意最后一条规则:Both operands are promoted to int
  • @duskwuff 是全球运营商,不是会员

标签: c++ c++11 casting bit-manipulation


【解决方案1】:

问题似乎在于按位转换的输出始终是整数,不一定反映输入类型。这是真的吗?

从早期的 C 语言开始,对小于int的类型的数学运算会将类型提升为int

原因——当int 是“大整数类型”时——升级到int 会很便宜并且可以防止一些溢出情况。

如果是这样,有没有办法为它指定一个类型,这样我就不必每次都显式转换?

是的!定义操作,而不是接受默认生成的实现。

ErrorType& operator |= ( ErrorType &left, ErrorType right )
{
    return left = ErrorType(left | right);
}

【讨论】:

  • @SergeyA 哪里有无限递归?
  • @PiotrSkotnicki 我的错
【解决方案2】:

当枚举不存在重载运算符时,内置运算符版本上的按位运算求助,在将枚举提升为其底层类型后,您可以将其显式转换为:

this->errorType = static_cast<ErrorType>(errorType | ERROR01);

或重载|= 运算符以允许:

ErrorType& operator|=(ErrorType& lhs, ErrorType rhs) {
    lhs = static_cast<ErrorType>(lhs | rhs);
    return lhs;
}

void S::setError1()
{
    this->errorType |= ERROR01;
}

【讨论】:

  • 非常好。但我认为我们应该在这里巧妙地指出。请注意,您不仅覆盖了operator|,否则会导致无限递归,除非您手动将参数转换为 int。覆盖这些运算符必须小心谨慎,因为会发生自动转换,而且并不总是很明显会发生什么。
  • @PiotrSkotnicki 谢谢,我正要做出改变。
【解决方案3】:

是的,按位运算的结果是提升后的整数类型。当两个整数操作数参与算术运算时,它们首先被提升至少为int 类型,其中对ints 执行运算,结果为int。没有从int 到枚举的隐式转换,所以你必须自己回滚。

更多积分促销规则:https://en.cppreference.com/w/cpp/language/implicit_conversion#Integral_promotion

【讨论】:

    猜你喜欢
    • 2018-08-28
    • 2016-08-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多