c - 循环 C 中的位

标签 c

我是 C 新手,我想根据以下过程将输入位存储到输出数组。

input           MSB                  LSB MSB                  LSB MSB              
[169,48,0] =     1  0  1  0  1  0  0  1   0  0  1  1  0  0  0  0   0  0  0  0  0  0  0  0 

程序应该遍历输入数据以找到起始索引出现在哪个字节中,并提取从起始索引到结束索引的位并将其存储在输出 [] 中。例如,我的起始索引是 4,它存在于 input[0] 中,我的结束索引是 13。所以我需要从位位置 4 到 13 中提取并将其放在 output[] 中。

当我说位位置 4 到 13 时,我的意思是 - 我需要来自输入 [0] 的位 [4 - 7] = {0 1 0 0 1} 和位 [8 - 13] = {1 1 0 0 0 0} 来自输入[1]

expected
output
[9, 48,0] =     0  0  0  0  1  0  0  1   0  0  1  1  0  0  0  0   0  0  0  0  0  0  0  0

我尝试用 C 编程,但不幸的是我没有成功,位循环是通过 LSB 到 MSB。我需要循环第一个字节并继续下一个字节并重复直到出现结束位置的字节索引。

#include<stdio.h>
int main()
{
    unsigned char input[3] = {169,48,0};
    unsigned char output[3]= {0};
    int i, start = 4, end = 13;
    for(i=0; i<3; i++)
    {
        output[i] = (input[i] >> (start)) & ((1u << (end)) -1u);
        printf("%u\n",output[i]);
    }
    return 0;
}

程序循环遍历所有 3 个输入字节,并从位索引 4 存储到该特定字节的结束索引,即 7。

output
[10, 3, 0] =     0  0  0  0  1  0  1  0   0  0  0  0  0  0  1  1   0  0  0  0  0  0  0  0 

我想检查我的起始索引是否存在于 input[0] 或 input[1] 或 . . . input[n],根据开头显示的预期输出,从起始索引复制并存储到结束索引(可能存在于任何字节位置)。

如果您能更正程序逻辑,我将不胜感激,因为我是 C 语言的新手。

最佳答案

欢迎来到论坛。

I would be greatfull if you could correct the program logic as I'm new to C.

这是一个尝试性的尝试。您的主要逻辑在以下行中:

output[i] = (input[i] >> (start)) & ((1u << (end)) -1u);

通过将其简化为以下内容(并使用临时 unsigned char 变量 tmp),这更容易分析:

tmp = input[i] >> start; // (1)
tmp &= (1u << end) - 1u; // (2)
// etc.

我不清楚你在这里到底想做什么。我相信您应该尝试做的是从 input[i]start 中提取 8-startinput[i+1] 中的位并将这些值(适当移位)的逻辑或放在临时变量中。如果是这样,那么我的建议如下。

在第一行 (1) 中你移动了错误的方向:它应该是

tmp = input[i] << start;

下一行 (2) 没有完成任何事情。 (你实际上是 AND'ing 为零。)另外,你应该使用 |而不是 &,第二个操作数应该是从下一个字节开始选择的位(适当移位)。

tmp |= input[i+1] >> (8-start);

这就是提取阶段。接下来是输出流中的插入 阶段。上面没有讨论更多的细微差别,但给出了一般的想法。 (有关处理更多详细信息的实现,请参见下文。)

I want to check whether my start index is present in input[0] or input[1] or . . . input[n]

为此用途

int idx = start / 8; // byte index
int offset = start % 8; // bit position within byte

P.S.您最初的问题表明,输出流中提取的位的偏移量可能与输入流中的不同。您的编辑隐藏了这一事实,但下面的实现允许这种可能性(“换位”)。

可能的实现

void transpose_bits(unsigned char *a, unsigned char *b, int start, int end, int dest, size_t array_len) {
    unsigned char tmp = '\0', tmp2 = '\0';
    int offset = 0, idx = 0, len = 0, next_bits = 0;
    char bitmask = 0x80;

    len = end - start;
    while (len > 0) {
        // Single pass - transpose up to 8 bits ...
        tmp = tmp2 = '\0';

        // Determine the byte index and offset in the input byte array.
        idx = start / 8;
        offset = start % 8;
        tmp = a[idx] << offset;
        next_bits = offset + len - 8;
        if (next_bits < 0) {
            // Don't even need all of current byte  => remove trailing bits ...
            tmp &= bitmask >> (len - 1);
        } else if (next_bits > 0) {
            // Need to include part of next byte ...
            tmp2 = a[idx + 1] & (bitmask >> (next_bits - 1));
            tmp |= tmp2 >> (8 - offset);
        }

        // Determine byte index and offset in output byte array
        idx = dest / 8;
        offset = dest % 8;
        b[idx] |= tmp >> offset;
        b[idx + 1] |= tmp << (8 - offset);
        // Update start position and length for next pass ...
        if (len > 8) {
            len -= 8;
            dest += 8;
            start += 8;
        } else
            len -= len;
    }
}

示例用法:

// Extract bits: 'start' and 'dest' are the same.
transpose_bits(input, output, 4, 13, 4, 3); // Assume arrays are of length '3'

// Transpose bits: 'start' and 'dest' not the same.
transpose_bits(input, output, 4, 13, 10, 3);

注意事项:

  • char[] 数组必须是无符号的(因为您已正确选择)- 因为右移运算符对有符号值的处理方式不同。
  • 您应该检查数组的边界(将 idxarray_len 进行比较);为简洁起见,我在这里跳过了这一点
  • transpose_bits() 函数的 while() 循环中的每次迭代最多可以处理 8 位。通过使用多次传递,它可以处理任意数量的数据。

关于c - 循环 C 中的位,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50898380/

相关文章:

c - 使用递归来反转字符串 - C

c - 如何在 c 中显示所有接口(interface) IPv6/前缀地址

c - 指向函数的 Typedef 结构指针 (C)

objective-c - 使用 LLVM 5 在 Objective-C 的结构中声明枚举

c - 编译后生成奇怪的汇编代码

c - 使用自动变量编译 Makefile

c - 我怎样才能阻止文件扫描器读取最大数量后的整数

c - 在 C 中访问二维位数组中特定位的最快方法?

c - 在链表 C 中使用 free() 和内存分配

c - 对数组进行排序 - C 语言