繁体   English   中英

使用联合测试字节数组中位的有效方法?

[英]Efficient way to test bits in a byte array using a union?

我的数据有时最好被视为一个 10 字节的数组,有时是一个 80 位的数组。 也许是工会的工作?

用 10 个字节填充数组后,我扫描 80 位并测试是否设置。 在 ISR 中,扫描是逐位推进的,因此效率是关键。

现在我在每次中断时都这样做:

 volatile uint8_t bit_array[10]; // external to ISR
 volatile uint8_t bit_idx;
 volatile uint8_t byte_idx;
 
 // -----ISR---------
 
 static uint8_t abyte;   // temp byte from array

 if (bit_idx == 0) {     // at each new byte
   bit_idx = 1;          // begin at the lowest bit
   abyte = bit_array[byte_idx];
 }
 if (abyte & bit_idx) {
   // << do the thing >>
 }
 if ((bit_idx *= 2) == 0) { // idx << and test for done
   if (++byte_idx > 9) {    // try next byte
     byte_idx = 0;
     fill_array_again();
   }
 }
 

我有一种感觉,有一种方法可以创建一个联合,允许使用单个索引 0..79 直接扫描位,但我不太了解尝试它。

问题是:我可以这样做吗? 并且:它可以有效吗?

您可以使用0 ... 79范围作为索引,而无需联合1 您可以使用index / 8获取数组中的字节索引,使用index % 8获取位位置(在该字节内)。

这肯定会简化您的代码; 但是,它是否会显着提高效率将取决于许多因素,例如目标 CPU 是什么以及编译器的智能程度。 但请注意,对于大多数编译器/架构来说,以8作为 RHS 的除法和余数运算是微不足道的,并且分别减少为位移位和简单掩码。

这是一个可能的大纲实现:

uint8_t data[10]; // The 10 bytes
uint8_t index = 0; // index of bits in 0 .. 79 range

void TestISR()
{
    // Test the indexed bit using combination of division and remainder ...
    if (data[index / 8] & (1 << (index % 8))) {
        // Do something
    }
    // Increment index ...
    if (++index > 79) {
        index = 0;
        refill_array();
    }
}

对于任何未能实现优化除法和余数运算的编译器,可以重写if语句:

    if (data[index >> 3] & (1 << (index & 7))) {
        // ...

1请注意,任何实际使用联合的尝试都可能表现出未定义的行为。 在 C++ 中,从不是最后一个写入的联合成员中读取的是 UB(尽管它在 C 中是可以接受且定义明确的)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM