n个字节的第7个低位的级联

Concatenation of the 7th lower bits of n bytes

本文关键字:级联 7个 字节      更新时间:2023-10-16

我只是想知道这两个表达式之间是否有区别:

1:a = ( a | ( b&0x7F ) >> 7 );

2:a = ( ( a << 8 ) | ( b&0x7F ) << 1 );

我说的不仅仅是结果,还有效率(但第一个看起来更好)。

目的是连接多个字节的7个低位,我最初使用的数字2是这样的:

while(thereIsByte)
{
  a = ( ( a << 8 ) | ( b&0x7F ) << i );
  ++i;
}

谢谢。

这两个表达式没有做任何相似的事情:

  1. 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`
  1. 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

如果你想在a中连接b的最低7位,应该是:

while (thereIsByte) {
    a = (a << 7) | (b & 0x7f);
    // read the next byte into `b`
}

例如,如果sizeof(a)=4个字节,并且您正在连接四个7位的信息,则伪代码的结果将是:

a = uuuuzzzzzzzyyyyyyyxxxxxxxwwwwwww

其中z是读取的第一个字节的7位,y是读取的第二个字节的8位,依此类推。u是未使用的位(包含a的最低4位中的信息)

在这种情况下,a的大小需要大于您想要连接的总比特数(例如:如果您想要连接四个7比特的信息,则至少为32比特)。

如果ab是一个字节的大小,那么就不会有太多的级联,您可能需要像boost::dynamic_bitset这样的数据结构,在这种结构中,您可以多次附加位,并且它可以同时增长。

是的,它们不同。在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个位)并读取。基本上,这是由操作顺序引起的。第一种方法更为优化,但移位是计算机最有效的操作之一,对于大多数应用程序来说,这种差异可能可以忽略不计。

请注意,编译器将它们视为字节,而不是带符号的int。