我在网上发现了一些执行此任务的代码:
byte = byte >> field;
byte = byte & 0x01;
return(byte);
但是,我不明白为什么我们不能这样做:
return(byte & field);
这会有用吗?为什么或者为什么不?是否有更好的实施?
答案 0 :(得分:3)
第一个相当于:
return (byte >> field) & 0x01;
它真正做的是转移到位置为field
的位,如果该位置位则返回1
,否则为0
。
您建议的那个是不正确的,因为它不会移动到指定字段的偏移量。例如,byte & 5
没有任何意义。
该功能也可以这样写:
return byte & (1 << field);
当然,如果您打算将1 << 5
传递给它而不是5
,您可以按照自己的方式编写。
我认为field
是一个数字,表示我们感兴趣的位的位置,因此对于单个字节,它将在0..7
范围内。
答案 1 :(得分:1)
在第一个代码示例中,field是您想要该值的字段中位的位置。
在第二个样本中,字段必须是一个int,该位设置为1,即1 << field
。
答案 2 :(得分:1)
如果你真的希望返回值为零或者你可以
return ((byte & (1 << field)) != 0);
或
return ((byte >> field) & 0x01);
如果您关心的只是返回值为零或非零,则两种形式都会简化一些。
答案 3 :(得分:1)
field
表示从右侧(LSB)获得的单词的位数。 byte = byte >> field
会将字节field
的位号byte
置于LSB位置。然后byte = byte & 0x01
和0x01
的字节,这意味着如果最初在位号1
中设置了位,则结果将在LSB中包含field
,或者将包含如果在该位置清除了位,则0
。
例如,检查字节0x52
是否设置了位号4
所需的测试如下所示。
byte = 0x52 = 0 1 0 1 0 0 1 0
field = 0x04 = 0 0 0 0 0 1 0 0
Operation: byte = byte >> field
The bit number 4 is single quoted below. Note how it moves
intermediate byte | lost bits during
states | right shifting
byte = 0x52 = 0 1 0 '1' 0 0 1 0 |
shift 1 = 0x29 = 0 0 1 0 '1' 0 0 1 | 0
shift 2 = 0x14 = 0 0 0 1 0 '1' 0 0 | 1 0
shift 3 = 0x0A = 0 0 0 0 1 0 '1' 0 | 0 1 0
shift 4 = 0x05 = 0 0 0 0 0 1 0 '1' | 0 0 1 0
Note that the bit 4 is now moved at the LSB/righ most position of the byte
now if we test the rightmost position of the above byte then we can check
if the bit number 4 had its bit set or cleared, with the following operation
Operation: byte = byte & 0x01
byte is now 0x05
byte = 0x05 = 0 0 0 0 0 1 0 '1'
AND & & & & & & & &
0x01 = 0 0 0 0 0 0 0 1
---- ----------------
0x01 0 0 0 0 0 0 0 1
Now byte contains 0x01 so bit number 4 had the bit set. In the other case the
final answer would be 0.
但我们无法执行byte & field
来检查编号为field
的位是否已设置或清除。这是因为field
只是二进制而不是掩码。如果我们byte & field
,则会发生以下情况。
byte = 0x52 = 0 1 0 1 0 0 1 0
AND & & & & & & & &
field = 0x04 = 0 0 0 0 0 1 0 0
---- ---------------
0x00 0 0 0 0 0 0 0 0
field
的值为0x04
,即其位数2
已设置。通过此操作,我们实际检查了是否设置了位号2
。如果field
的值为5
,则会设置位0
和2
,因此如果提取位{{1 {}}和0
的值2
,可以采用四种可能的组合。
测试byte
的位值的其他方法不是移动byte
本身,而是将byte
掩码0x01
向左移动,并且AND它与字节,并检查是否为零。 field
编号位置位时(byte & (0x01 << field)) != 0
为真,否则为假。
field
如果你有一个需要定期测试的特定格式的字节,例如某些预先定义的字的某个位域,其中每个位意味着某些特定的东西,那么你可以保留预编译器掩码,它只有一个特定的将使用该掩码测试的位位置。例如,要检查一个字节,预计算机掩码将是:
Operation: (0x01 << field)
Shifting 0x01 to the left field times field = 0x04 for the example
= 0x01 = 0 0 0 0 0 0 0 1
shift 1 = 0x02 = 0 0 0 0 0 0 1 0
shift 2 = 0x04 = 0 0 0 0 0 1 0 0
shift 3 = 0x08 = 0 0 0 0 1 0 0 0
shift 4 = 0x10 = 0 0 0 1 0 0 0 0
After the left shift the '1' moves in the bit position 4
Now we AND this with the byte to check if the bit position 4
is set or clear.
byte = 0x52 = 0 1 0 1 0 0 1 0
AND & & & & & & & &
(0x01 << field) = 0x10 = 0 0 0 1 0 0 0 0
---- ---------------
0x10 0 0 0 1 0 0 0 0
Therefore the answer (0x01 != 0) is 1 there fore the bit 4 is set. It the bit 4
was not set then the answer would be 0.
为了测试#define BIT_0 0x01 //(00000001)
#define BIT_1 0x02 //(00000010)
#define BIT_2 0x04 //(00000100)
#define BIT_3 0x08 //(00001000)
#define BIT_4 0x10 //(00010000)
#define BIT_5 0x20 //(00100000)
#define BIT_6 0x40 //(01000000)
#define BIT_7 0x80 //(10000000)
中的第4位,我们必须byte
或return (byte & BIT_4)
根据位位置的含义,可以设置宏的名称。
答案 4 :(得分:0)
第一个示例将所需位移入返回的LSB,但第二个示例只是屏蔽掉所有不需要的位。
答案 5 :(得分:-1)
这可以通过结构给出。让我们说:
struct POWERTRAIN_ERROR
{
uint8 ERROR_CODE;
unit8 LAMP_STATUS : 1;
};
struct POWERTRAIN_ERROR pt_error;
uint8 func ( struct POWERTRAIN_ERROR pt)
{
// do something with pt.ERROR_CODE (which is a byte) and pt.LAMP_STATUS which is a bit field
// lets say, this function needs to return the status of 0th bit of ERROR_CODE
return ( pt.ERROR_CODE & 0x1) ;
}