首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >c++和按位操作中的联合

c++和按位操作中的联合
EN

Stack Overflow用户
提问于 2016-05-18 17:56:34
回答 1查看 1.4K关注 0票数 3

我在源代码中看到了以下结构。

代码语言:javascript
复制
template<unsigned bitno, unsigned nbits = 1, typename T = u8>
struct RegBit
{
    T data;
    enum { mask = (1u << nbits) - 1u };
    template<typename T2>
    RegBit& operator=(T2 val)
    {
        data = (data & ~(mask << bitno)) | ((nbits > 1 ? val & mask : !!val) << bitno);
        return *this;
    }
    operator unsigned() const { return (data >> bitno) & mask; }
};

union {
    u8 raw;
    RegBit<0> r0;
    RegBit<1> r1;
    RegBit<2> r2;
    RegBit<3> r3;
    RegBit<6> r6;
    RegBit<7> r7;
} P;

在第一次阅读之后,我发现类型为RegBit的对象的RegBit强制转换将返回data的位号bitno + 1

但是,我不明白如何处理=重载操作符。我的意思是我理解语法,但不是按位操作的目的。

最后,如果运行代码并将值影响到P.raw,您将注意到∀i∈0;7,P.ri.data = P.raw

这怎么可能?当然,代码执行它应该做的事情,例如:(unsigned)P.ri i∈0;7,i+1是P.raw__的第四位。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-05-18 21:13:10

operator=是如何工作的?

编写P.r2 = 1;时,将调用r2成员的赋值运算符。因此,它将具有P.r2.operator= (1);的效果,它将返回对P.r2的引用。

让我们以bitno=2nbits=1Tu8来分析专用模板中的赋值细节:

代码语言:javascript
复制
mask = (1u << nbits) - 1u   
     = (1 shifted by 1 bits, aka binary 10) - 1
     = binary 1  (i.e.  it's a binary number with the n lowest bits set)

让我们一步一步地分析整个表达方式。首先是左边的部分:

代码语言:javascript
复制
mask << bitno ===> binary 100
~(mask << bitno)  ===> binary 1..1011  (aka the bit bitno is set to 0, counting from least significant bit) 
(data & ~(mask << bitno))  ===> the bit bitno is set to 0 in data (thanks to the bitwise &)  

现在,表达式的正确部分是:

代码语言:javascript
复制
(nbits > 1 ? val & mask : !!val) is a conditional operator:  
   if nbits >1 is true, then it's val&mask, aka the n lowest bits of val
   if not, then it's !!val, aka "not not val" which evalauates to 0 if val is 0 and 1 if val is not 0.  
In our case, it's the second alternative so 0 or 1 depending on val.  
((nbits > 1 ? val & mask : !!val) << bitno)  then shifts the 0 or the 1 by 2 bits.  

现在,最后将所有这些结合起来:

代码语言:javascript
复制
data = (data & ~(mask << bitno)) | ((nbits > 1 ? val & mask : !!val) << bitno);

      = (data with the bit bitno set to 0) ored with (val expressed on one bit in the bit bitno, counting from the least significant )

否则,当位值0与位值x作为结果(位值x)时,该表达式将位位值设置为val (作为bool处理的val)。

但是工会应该做什么呢?

该联盟在同一个内存位置处理其所有成员(它们都是相同类型的u8)。

那么,根据您预期的输出结果是什么呢?

代码语言:javascript
复制
P.raw=0; 
P.r2=1; 
P.r3=0;  
P.r4=1;  
cout << (int)P.raw <<endl;  

编写代码片段的乐观主义者当然期望得到20 (也就是二进制10100)的结果。这在许多编译器上可能会像这样工作。但在现实中,这是绝对不能按照标准保证的:

9.5/1:在一个联合中,最多一个非静态数据成员可以在任何时候都是活动的,也就是说,的值最多可以在任何时候存储在一个中的非静态数据成员中。

否则,如果您将某些内容存储在r2中,则无法确定您是否会在r4中找到相同的值。唯一可以肯定的是,如果您在r2中存储了一些东西,而没有在其他成员中存储任何东西,那么您将在r2中找到您在那里存储的内容。

工会的替代方案

如果需要确保可移植性,可以考虑使用std::bitset或标准位域

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37306963

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档