繁体   English   中英

c ++中的联合和按位运算

[英]Unions in c++ and bitwise operations

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

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;

第一读取后,我发现一个unsigned一个对象,其类型的铸造是RegBit将返回的比特数bitno + 1data

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

最后,如果你运行代码并影响P.raw的值,你会注意到P.raw [0; 7], P.ri.data = P.raw

怎么可能? 当然然后,将码做什么它假定至IMHO做,即:∀我∈[0; 7], (unsigned)P.ri是第(i + 1)个的位P.raw

运营商如何工作?

当你写P.r2 = 1; ,调用r2成员的赋值运算符。 所以它会产生P.r2.operator= (1);的效果P.r2.operator= (1); 返回对P.r2的引用。

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

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)

让我们一步一步地分析完整的表达。 首先左边部分:

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 &)  

现在表达的正确部分:

(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.  

现在最后结合所有这些:

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 )

否则说明,作为位值x的位值0给出位值x的结果,该表达式将位bitno设置为val(val被处理为bool)。

但联盟应该做什么呢?

联合处理同一内存位置中的所有成员(它们都是相同的类型u8 )。

那么根据你的预期输出如下:

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或标准位域

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM