C中带有移位的复合运算符或如何转换20bit 2'32位有符号整数中的补码数
Compound operator with shift in C or how to convert 20bit 2'complement number in 32bit signed int
有20位2’complement数字(用3 x 8位读取(,需要转换为32位带符号整数。
有人能解释一下这段代码吗:
int32_t sample = 0;
sample |= SPI.transfer(0);
sample <<= 8;
sample |= SPI.transfer(0);
sample <<= 8;
sample |= SPI.transfer(0);
sample <<= 8;
sample /= 1L << 12;
所以现在在右边的32位有符号整数中有24个值,然后:
sample /= 1L << 12;
这是怎么回事?
完整代码的链接位于:
https://github.com/circuitar/Nanoshield_LoadCell/blob/master/src/Nanoshield_LoadCell.cpp
这是如何工作的?
如果SPI.transfer(0)
返回0-255;作品";当20比特数在读取的数据的高24比特中时。然后,将其转换为32位类型的符号位依赖于UB来形成正确的值,当被划分时,但1 << 12
是受欢迎的值。
要将20位2的补码数转换为int32_t
,请测试符号位。
// Alternative without UB nor implementation defined behavior:
int32_t sample = 0;
sample |= SPI.transfer(0);
sample <<= 8;
sample |= SPI.transfer(0);
sample <<= 8;
sample |= SPI.transfer(0);
// if input is in upper 20 bits of the 24 read (OP is not explicit on that)
if (1) {
sample >>= 4;
}
assert(sample >= 0 && sample <= 0xFFFFF);
if (sample & 0x80000) { // Test for the 20-bit 2's complement sign bit
sample -= 0x100000;
}
通常,应该对无符号整数类型执行逐位移位操作,因为:
- 左移负值会导致未定义的行为
- 如果将任何非零位移位到符号位的位置或通过符号位的该位置,则对非负的有符号值进行左移位会导致未定义的行为
- 对负值进行右移将生成实现定义的值
如果你小心避免以上所有情况,逐位移位操作可以在有符号整数类型上使用,如下所示1:
int32_t sample = 0;
sample |= SPI.transfer(0);
sample <<= 8;
sample |= SPI.transfer(0);
sample <<= 8;
sample |= SPI.transfer(0);
sample >>= 4;
// 'sample' contains a 20-bit, 2's complement value. Sign-extend to a 32-bit signed value.
if (sample >= (INT32_C(1) << 19))
sample -= (INT32_C(1) << 20);
if (sample >= ...
符号扩展部分可能不是无分支的,具体取决于编译器。从20位2的补码到32位有符号的另一种符号扩展转换是:
sample = (sample ^ (INT32_C(1) << 19)) - (INT32_C(1) << 20);
XOR运算将2的补码值转换为偏移二进制值。该操作可以合并到来自第一次SPI传输的字节值中(20位采样值的最高有效8位(,如下所示:
int32_t sample = 0;
sample |= SPI.transfer(0) ^ 0x80; // convert 2's complement to offset binary
sample <<= 8;
sample |= SPI.transfer(0);
sample <<= 8;
sample |= SPI.transfer(0);
sample >>= 4;
// 'sample' contains a 20-bit, offset binary value. Convert to 32-bit, signed value.
sample -= INT32_C(1) << 20;
1";便携式";这里只要CCD_ 5是由实现提供的。如果不是,则可以使用int_least32_t
。
相关文章:
- 在C++中,将大的无符号浮点数四舍五入为整数的最佳方法是什么
- 有符号的int和int-有没有一种方法可以在C++中区分它们
- 将无符号char*转换为std::istream*C++
- 如何在C++中将一个无符号的 int 转换为两个无符号的短裤?
- vscode g++链路故障:体系结构x86_64的未定义符号
- 从矢量<无符号字符>转换为字符* 包括垃圾数据
- 如何理解将半精度指针转换为无符号长指针和相关的内存对齐
- Visual studio代码重构似乎不起作用(例如,重命名符号-f2)
- 使用gcc从静态链接的文件中查找可选符号
- C++中无符号字符溢出
- 使用无符号字符数组有效存储内存
- C++:Application.cpp中抛出了未解析的外部符号(解决方案在问题的末尾,供未来的读者参考)
- VC++本机单元测试,找不到调试符号
- 为什么我必须在C++中添加一个赋值符号来声明一个数组
- 检查TCHAR数组输入是否为带符号整数C++
- 用符号版本替换对函数的所有调用
- 未解析的外部符号_MsiLocateComponentW@12.
- 如何打印boost多精度128位无符号整数
- C++模板函数,用于比较任何无符号整数和有符号整数
- 在 Mac 上使用 CMAKE 将 FFTW 和 FFTWPP 链接到项目中时未定义的符号