Bitshift - 需要解释才能理解代码

cpp*_*ame 3 c c++ bit-manipulation bit-shift

我想知道这个功能实际上是什么.根据我的理解,它应该返回pSrc [1].

那么为什么它会将左移pSrc [0]加扰8位,这会将这8位清零.当这些零与pSrc [1]进行"或"运算时,pSrc [1]不受影响,因此无论如何都会得到pSrc [1],就像从未发生过按位OR一样.

/*
* Get 2 big-endian bytes.
*/
INLINE u2 get2BE(unsigned char const* pSrc)
{
    return (pSrc[0] << 8) | pSrc[1];
}
Run Code Online (Sandbox Code Playgroud)

此功能来自dalvik虚拟机的源代码. https://android.googlesource.com/platform/dalvik/+/android-4.4.4_r1/vm/Bits.h

更新:

好的,现在我得到了它,感谢这里的所有答案.

(1)pSrc [0]最初是无符号字符(1字节).

(2)当使用int类型的文字8左移(pSrc [0] << 8)时,pSrc [0]因此被int提升为signed int(4字节).

(3)pSrc [0] << 8的结果是pSrc [0]中感兴趣的8位被移位到signed int的4个字节的第二个字节,从而在其他字节中留下零(1st,第3和第4个字节).

(4)当ORed(步骤(3)的中间结果| pSrc [1])时,pSrc [1]然后被int提升为signed int(4字节).

(5)(步骤(3)| pSrc [1]的中间结果)的结果以两个最高有效字节中的所有零的形式留下前两个最低有效字节.

(6)通过将结果作为u2类型返回,仅返回前两个最低有效字节以获得2个大端字节.

chr*_*ris 8

对于像这样的算术运算,unsigned char通过称为积分促销的过程转换.

C++ 11 - N3485§5.8[expr.shift]/1:

操作数应为整数或无范围的枚举类型,并执行整体促销.结果的类型是提升的左操作数的类型.

并且§13.6[over.built]/17:

对于每对提升的整数类型L和R,存在该形式的候选运算符函数

LR operator%(L , R );
LR operator&(L , R );
LR operator^(L , R );
LR operator|(L , R );
L operator<<(L , R );
L operator>>(L , R );
Run Code Online (Sandbox Code Playgroud)

其中LR是类型L和R之间通常的算术转换的结果.

完成整体促销后(§4.5[conv.prom]/1):

如果int可以表示源类型的所有值,则除了bool,char16_t,char32_t或wchar_t之外的整数类型的prvalue(其整数转换等级(4.13)小于int的等级)可以转换为int类型的prvalue ; 否则,源prvalue可以转换为unsigned int类型的prvalue.

通过整体促销,unsigned char将被提升为int.另一个操作数已经存在int,因此不会对其进行类型更改.然后返回类型也变为int.

因此,你所拥有的是第一个unsigned char向左移位的位,但仍然在现在更大int,然后是最后的第二unsigned char位.

您会注意到返回类型operator|是两个操作数之间通常算术转换的结果.在这一点上,那些是int从转移和第二unsigned char.

此转换定义如下(§5[expr]/10):

许多期望算术或枚举类型的操作数的二元运算符会以类似的方式引起转换并产生结果类型.目的是产生一个通用类型,它也是结果的类型.这种模式称为通常的算术转换,定义如下:
......
否则,应对两个操作数执行整数提升(4.5).然后,以下规则应用于提升的操作数:
...
如果两个操作数具有相同的类型,则不需要进一步转换.

由于L并且R在此之前被提升int,因此促销使它们保持相同,因此表达式的整体返回类型int将被转换为u2,无论发生什么.

  • 你仍然得到"因为转变的右手论证是一个'int`".移位的右手参数对移位的类型和结果类型没有影响. (2认同)