我只是想知道这两个表达式之间是否有任何区别:
1:a = ( a | ( b&0x7F ) >> 7 );
2:a = ( ( a << 8 ) | ( b&0x7F ) << 1 );
我不仅谈论结果,还谈论效率(但第一个看起来更好)。
目的是连接多个字节的7个低位,我最初使用的是数字2,如下所示:
while(thereIsByte)
{
a = ( ( a << 8 ) | ( b&0x7F ) << i );
++i;
}
感谢。
答案 0 :(得分:4)
这两个表达式没有任何相似之处:
a = ( a | ( b&0x7F ) >> 7 );
<强>解释强>
a = 0010001000100011
b = 1000100010001100
0x7f = 0000000001111111
b&0x7f = 0000000000001100
(b&0x7f) >> 7 = 0000000000000000 (this is always 0), you are selecting the lowest
7 bits of 'b' and shifting right 7bit, discarding
the selected bits).
(a | (b&0x7f) >> 7) always is equal to `a`
a = ( ( a << 8 ) | ( b&0x7F ) << 1 );
<强>解释强>
a = 0010001000100011
b = 1000100010001100
0x7f = 0000000001111111
b&0x7f = 0000000000001100
(b&0x7f) << 1 = 0000000000011000
(a << 8) = 0010001100000000
(a << 8) | (b&0x7F) << 1 = 0010001100011000
在第二个表达式中,结果将具有a
的3个最低字节作为3个最高字节,而b
的最低字节没有最高位,向左移位1位。行a = a * 256 + (b & 0x7f) * 2
如果要连接b
中a
的最低7位,则为:
while (thereIsByte) {
a = (a << 7) | (b & 0x7f);
// read the next byte into `b`
}
例如,在sizeof(a)
= 4个字节的情况下,并且您连接了4个7位信息,伪代码的结果将是:
a = uuuuzzzzzzzyyyyyyyxxxxxxxwwwwwww
z
是第一个字节的7位,y
是第二个字节的7位,依此类推。 u
是未使用的位(包含开头a
最低4位的信息)
在这种情况下,a
的大小需要大于要连接的总位数(例如:如果要连接四个7位信息,则至少为32位)。
如果a
和b
是一个字节大小不会真正连接,你可能需要一个像boost::dynamic_bitset
这样的数据结构,在那里你可以多次追加位并且它会增长accondinly。
答案 1 :(得分:1)
是的,他们是不同的。在MSVC2010上,当a和b都是字符时,这里是反汇编。
a = ( a | ( b&0x7F ) >> 7 );
012713A6 movsx eax,byte ptr [a]
012713AA movsx ecx,byte ptr [b]
012713AE and ecx,7Fh
012713B1 sar ecx,7
012713B4 or eax,ecx
012713B6 mov byte ptr [a],al
a = ( ( a << 8 ) | ( b&0x7F ) << 1 );
012813A6 movsx eax,byte ptr [a]
012813AA shl eax,8
012813AD movsx ecx,byte ptr [b]
012813B1 and ecx,7Fh
012813B4 shl ecx,1
012813B6 or eax,ecx
012813B8 mov byte ptr [a],al
请注意,第二种方法执行两次移位操作(总共9个移位位,每个位移一个时钟周期),而第一种方法执行单次移位(仅7位)并读取。基本上这是由操作顺序引起的。第一种方法更加优化,但是移位是计算机最有效的操作之一,对于大多数应用来说,这种差异可能是微不足道的。
请注意,编译器将它们视为字节,而不是签名的整数。