将int8转换为int7的最快方法

时间:2019-01-30 13:36:50

标签: c++ c performance bit-manipulation

我有一个函数,它使用int8_t val并将其转换为int7_t

//Bit [7] reserved
//Bits [6:0] = signed -64 to +63 offset value
// user who calls this function will use it correctly (-64 to +63)
uint8_t func_int7_t(int8_t val){
    uint8_t val_6 = val & 0b01111111;
    if (val & 0x80)
        val_6 |= 0x40;
    //...
    //do stuff...
    return val_6;
}

将int8转换为int7的最快最快方式是什么?我做到了快速高效吗?还是有更好的方法?

如果需要的话,目标是ARM Cortex M0 +

更新:

在阅读了不同的答案之后,我可以说这个问题被问错了吗? (或者我的问题代码是给别人错误的假设)我有意将int8改为int7

所以什么都不做,因为

8位:

 63 = 0011 1111
 62 = 0011 1110
  0 = 0000 0000
 -1 = 1111 1111
 -2 = 1111 1110
-63 = 1100 0001
-64 = 1100 0000

7位:

 63 = 011 1111
 62 = 011 1110
  0 = 000 0000
 -1 = 111 1111
 -2 = 111 1110
-63 = 100 0001
-64 = 100 0000

5 个答案:

答案 0 :(得分:6)

最快的方法可能是:

uint8_t val_7 = (val & 0x3f) | ((val >> 1) & 0x40);

val & 0x3f得到6个低位(截断),((val >> 1) & 0x40)将该位从8移到7

不使用 if 的好处是代码较短(即使您可以使用算术 if ),并且代码没有序列中断

答案 1 :(得分:4)

要清除保留位,只需

return val & 0x7f;

要保留与输入完全相同的保留位,无需执行任何操作

return val;

,低7位将包含[-64,63]中的值。因为以二进制补码,向下转换是通过简单的截断完成的。该值保持不变。这就是(int8_t)some_int_value

这样的作业的结果

没有0bX1100001 之类的东西。机器语言中没有未定义的部分。该状态仅存在于硬件中,例如Verilog或其他硬件描述语言中的高Z状态或未定义状态

答案 2 :(得分:3)

使用位域来缩小值,并让编译器选择哪种移位和/或掩码序列对于您的平台上的序列最有效。

inline uint8_t to7bit(int8_t x) 
{ 
    struct {uint8_t x:7;} s; 
    return s.x = x; 
} 

答案 3 :(得分:2)

如果您不担心超出范围的值会发生什么,那么

return val & 0x7f;

就足够了。这样可以正确处理-64 <= val <= 63范围内的值。 您尚未说过要如何处理超出范围的值,所以我对此无话可说。

已更新为添加:该问题已更新,因此规定永远不要使用超出范围的值来调用该函数。因此,该方法无疑被称为“最佳和最快”。

答案 4 :(得分:1)

  

调用此函数的用户知道他应该将数据-64放入+63

因此,不考虑其他任何值,真的最快可以做的就是完全不做任何事情

您有一个8位存储的7位值。指定范围内的任何值将使第7位和第6位具有相同的值,并且当您处理7位值时,您只需忽略(8位值的)MSB,无论是否设置或不设置,e。 g。:

for(unsigned int bit = 0x40; bit; bit >>= 1)
//                NOT: 0x80!
    std::cout << (value & bit);

反之则更重要:每当您通过某个通信通道接收到这七个位时,就需要对八个(或更多)位进行手动符号扩展,以便能够正确使用该值。