我有一个函数,它使用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
答案 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);
反之则更重要:每当您通过某个通信通道接收到这七个位时,就需要对八个(或更多)位进行手动符号扩展,以便能够正确使用该值。