Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/57.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 如何将MSB复制到字节的其余部分?_C_Bit Manipulation_Microcontroller_Interrupt - Fatal编程技术网

C 如何将MSB复制到字节的其余部分?

C 如何将MSB复制到字节的其余部分?,c,bit-manipulation,microcontroller,interrupt,C,Bit Manipulation,Microcontroller,Interrupt,在中断子例程(每5µs调用一次)中,我需要检查一个字节的MSB并将其复制到该字节的其余部分 我需要做一些事情,比如: if(MSB == 1){byte = 0b11111111} else{byte = 0b00000000} 我需要它使它快速,因为它是在一个中断子例程上,而且上面还有一些代码,所以调用效率很高 因此,我不想使用任何if、switch、select或>操作数,因为我感觉这会减慢进程。如果我错了,那我就走“简单”的路 我所尝试的: byte = byte & 0b100

在中断子例程(每5µs调用一次)中,我需要检查一个字节的MSB并将其复制到该字节的其余部分

我需要做一些事情,比如:

if(MSB == 1){byte = 0b11111111}
else{byte = 0b00000000}
我需要它使它快速,因为它是在一个中断子例程上,而且上面还有一些代码,所以调用效率很高

因此,我不想使用任何if、switch、select或
>
操作数,因为我感觉这会减慢进程。如果我错了,那我就走“简单”的路

我所尝试的:

byte = byte & 0b100000000
这给了我
0b10000000
0b0000000

但是我需要第一个是
0b11111111


我想我错过了一个或某个地方(加上其他的大门)。我不知道,我的直觉告诉我,这应该很容易,但现在对我来说不是。

编辑:我的答案让人困惑,因为我没有指定无符号字节。这里我的假设是
B
属于
unsigned char
类型。正如下面的一条注释所述,我可以省略
&1
。这不如另一张海报上的带符号字节解决方案快,但这段代码应该是可移植的(一旦理解
B
是无符号类型)


负数是我们的朋友。顺便说一句,移位位应该很快。

诀窍是对
字节
变量使用有符号类型,如
int8\t
,并利用右移操作的符号扩展功能:

byte = byte >> 7;

右移速度非常快——在大多数现代(甚至不是那么现代)CPU上只需一条指令

其工作原理是有符号操作数上的
>
在左侧插入符号位以保留其操作数的符号。这称为符号扩展


注意:从技术上讲,此行为是由实现定义的,因此不具有普遍的可移植性。感谢您的评论和回答。

MSB实际上是数字的符号位。负数为1,正数为0。 所以最简单的方法就是

if(byte < 0)
{
    byte = -1;
}
else
{
    byte = 0;
}
if(字节<0)
{
字节=-1;
}
其他的
{
字节=0;
}
因为二进制中的-1=11111111



如果是无符号整数,只需将其转换为有符号值,然后如上所述再次进行比较。

这不是很好portable@EugeneSh. 是什么让你认为这是不可移植的?负数
1
并不是
111…1
在每种表示中都是如此
C
不保证2的补码。我在回答中假定为无符号类型。另一张海报有签名类型,比我的答案更有效。实际上,你可以省略
&1
,因为一个无符号字节的
B>>7
仅为1或0。而且,任何合适的优化器都可能会改变代码。您所展示的条件已经足够好了。而且它的可读性比任何比特黑客都强。你用的是C吗?或者,你是在asm中这样做的?如果您使用有符号右移方法,请查看微控制器的ISA参考手册,了解算术右移操作码,以确保[它可能有效]。或者,创建一个测试用例。在C语言中,只需反汇编代码,以确保获得预期的操作码。@Craig Estey:我在使用C。谢谢,我会记住这一点。@Eugene Sh:因为它是在一个中断子进程上,速度比清晰度更宝贵。如果不是,我会选择条件。只是在x86上测试了这个,做
m=(m&0x80)?0xFF:0x00
,带-O2将导致优化器生成一个
sar
inst(即它计算出来)。我认为这是可能的,因为我以前见过类似的“针孔”优化,用于像这样有用/常见的结构。所以,具有讽刺意味的是,您的第一个代码示例将生成最佳代码……这很可爱。对字节进行签名后,它就变得微不足道了。回答得好。位移位有符号负整数的结果是实现定义的@尤金尼什。感谢您的参考和评论,我已经习惯了将其作为算术移位来实现,以至于我没有意识到它是实现定义的。我编辑了答案以包含您的引用。有时非
int
类型的符号扩展需要不止一条指令:实际情况是编译器先左移24位,然后右移31位。如果是这样的话,它并不比比较后的条件移动好多少。@user3528438 OP只对一个字节进行操作,因此他的嵌入式编译器应该生成一条
ASR
指令。值-1不是所有1位所必需的,因为C允许使用其他有符号格式,比如1的补码和符号-magnitude@LưuVĩnhPhúc你能给我举个例子吗?-1可以是11111110的补码,10000001的符号大小,假设8位字节@LưuVĩnhPhúc,在这两种情况下(补码或符号大小),MSB保持不变(也就是说,1代表负数)。C中有符号类型的右移是不正确的。如果总是填充有符号位,那么-1可能会变成补码和符号大小的-0或-64
if(byte < 0)
{
    byte = -1;
}
else
{
    byte = 0;
}