C 读取字节之间的位

C 读取字节之间的位,c,memory,bit,C,Memory,Bit,我试图从字节缓冲区读取位。到目前为止,掩蔽和移位已经起作用,但是我不确定如何处理出现在字节之间的值,例如 ... 11001001 11101101 ... (read 8 bits from the buffer with 4 bit offset) |_______| 8和4不是静态的,可以不同,例如: ... 11001001 11101101 ... (read 7 bits from the buffer with 6 bit offset)

我试图从字节缓冲区读取位。到目前为止,掩蔽和移位已经起作用,但是我不确定如何处理出现在字节之间的值,例如

... 11001001 11101101 ... (read 8 bits from the buffer with 4 bit offset)
        |_______|         
8和4不是静态的,可以不同,例如:

... 11001001 11101101 ... (read 7 bits from the buffer with 6 bit offset)
    ^     |______|       
    |
  Buffer
我有一个起始偏移量,总共要读取位。但是我有一个char缓冲区,我不能使用chars将两个字节位移到一个字节中,或者我可以,所以我想这样做:

uint16_t two_byte_buffer;
memcpy(&two_byte_buffer, real_buffer, 2); // May need to endian convert ?
现在我可以对16位整数值进行位移位,读取所需的8位。这种方法有效吗?还有更好的方法吗

编辑:到目前为止,我已经使用这种方法从单个字符中提取位


那么以下内容如何:

#include <stdint.h>
#include <stdio.h>

#define BIG_ENDIAN_BUFFER

#ifdef BIG_ENDIAN_BUFFER
  #define EXTRACT(BUFFER, OFFSET) ((((BUFFER[0] << 8) | BUFFER[1]) >> (8 - OFFSET)) & 0xFF)
#else
  #define EXTRACT(BUFFER, OFFSET) ((((BUFFER[1] << 8) | BUFFER[0]) >> (8 - OFFSET)) & 0xFF)
#endif

int main(void)
{
    uint8_t real_buffer[] = {0xC9, 0xED};

    printf("0x%02X, 0x%02X, 0x%02X\n", real_buffer[0], real_buffer[1], EXTRACT(real_buffer, 0));
    printf("0x%02X, 0x%02X, 0x%02X\n", real_buffer[0], real_buffer[1], EXTRACT(real_buffer, 1));
    printf("0x%02X, 0x%02X, 0x%02X\n", real_buffer[0], real_buffer[1], EXTRACT(real_buffer, 2));
    printf("0x%02X, 0x%02X, 0x%02X\n", real_buffer[0], real_buffer[1], EXTRACT(real_buffer, 3));
    printf("0x%02X, 0x%02X, 0x%02X\n", real_buffer[0], real_buffer[1], EXTRACT(real_buffer, 4));
    printf("0x%02X, 0x%02X, 0x%02X\n", real_buffer[0], real_buffer[1], EXTRACT(real_buffer, 5));
    printf("0x%02X, 0x%02X, 0x%02X\n", real_buffer[0], real_buffer[1], EXTRACT(real_buffer, 6));
    printf("0x%02X, 0x%02X, 0x%02X\n", real_buffer[0], real_buffer[1], EXTRACT(real_buffer, 7));
    printf("0x%02X, 0x%02X, 0x%02X\n", real_buffer[0], real_buffer[1], EXTRACT(real_buffer, 8));

    return 0;
}
未定义大字节缓冲区时:


那么以下内容如何:

#include <stdint.h>
#include <stdio.h>

#define BIG_ENDIAN_BUFFER

#ifdef BIG_ENDIAN_BUFFER
  #define EXTRACT(BUFFER, OFFSET) ((((BUFFER[0] << 8) | BUFFER[1]) >> (8 - OFFSET)) & 0xFF)
#else
  #define EXTRACT(BUFFER, OFFSET) ((((BUFFER[1] << 8) | BUFFER[0]) >> (8 - OFFSET)) & 0xFF)
#endif

int main(void)
{
    uint8_t real_buffer[] = {0xC9, 0xED};

    printf("0x%02X, 0x%02X, 0x%02X\n", real_buffer[0], real_buffer[1], EXTRACT(real_buffer, 0));
    printf("0x%02X, 0x%02X, 0x%02X\n", real_buffer[0], real_buffer[1], EXTRACT(real_buffer, 1));
    printf("0x%02X, 0x%02X, 0x%02X\n", real_buffer[0], real_buffer[1], EXTRACT(real_buffer, 2));
    printf("0x%02X, 0x%02X, 0x%02X\n", real_buffer[0], real_buffer[1], EXTRACT(real_buffer, 3));
    printf("0x%02X, 0x%02X, 0x%02X\n", real_buffer[0], real_buffer[1], EXTRACT(real_buffer, 4));
    printf("0x%02X, 0x%02X, 0x%02X\n", real_buffer[0], real_buffer[1], EXTRACT(real_buffer, 5));
    printf("0x%02X, 0x%02X, 0x%02X\n", real_buffer[0], real_buffer[1], EXTRACT(real_buffer, 6));
    printf("0x%02X, 0x%02X, 0x%02X\n", real_buffer[0], real_buffer[1], EXTRACT(real_buffer, 7));
    printf("0x%02X, 0x%02X, 0x%02X\n", real_buffer[0], real_buffer[1], EXTRACT(real_buffer, 8));

    return 0;
}
未定义大字节缓冲区时:


您不需要将memcpy设置为16位就可以进行提取。试试这个,它适用于任意长度的字符数组。它分配足够的内存来保存提取的位

进口 进口 进口 字符缓冲区[]=任意值; int offset_位=12; 整数计数_位=34; 字符*结果; 无效打印字符*buf,整数位{ 对于int i=0;i>i%8&1; } printf\n; } int main{ int offset_bytes=偏移量_位/8; int shift_bits=偏移_bits%8; int count_bytes=count_bits-1/8+1; 结果=字符*malloc sizeofchar*计数字节;
forint i=0;i>shift_bits^buffer[i+offset_bytes+1]您不需要memcpy到16位就可以提取。试试看,它可以在任意长度的字符数组上工作。它分配足够的内存来保存提取的位

进口 进口 进口 字符缓冲区[]=任意值; int offset_位=12; 整数计数_位=34; 字符*结果; 无效打印字符*buf,整数位{ 对于int i=0;i>i%8&1; } printf\n; } int main{ int offset_bytes=偏移量_位/8; int shift_bits=偏移_bits%8; int count_bytes=count_bits-1/8+1; 结果=字符*malloc sizeofchar*计数字节; forint i=0;i>shift_位^buffer[i+偏移量_字节+1] 对于64位,只需更改类型即可



对于64位,只需更改类型即可

您能告诉我您想做什么吗?现在我可以对16位整数值进行位移位以读取所需的8位-而您不能使用real\u buffer执行此操作?real\u buffer是如何定义的?我不能使用chars uint8\u t value=real\u buffer[1]将两个字节位移位为一个字节>4&0x0f?@EugeneSh。我正在分析一个位编码的文件。@KamilCuk一个字符是8位的,我不需要移位8位的值,我需要移位至少16位的值才能得到下一个字符中的位。real\u buffer只是一个字符*,但它不代表ascii值,只代表二进制数据。写入uint16\u似乎是最好的方法。而不是memcpy我会使用双字节缓冲区=实字节缓冲区[n]你能告诉我你想做什么吗?现在我可以对16位整数值进行位移位来读取必要的8位-而你不能用实字节缓冲区来读取它?实字节缓冲区是如何定义的?我不能用chars uint8\u t value=实字节缓冲区[1]将两个字节位移位为一个字节>4&0x0f?@EugeneSh。我正在分析一个位编码的文件。@KamilCuk一个字符是8位的,我不需要移位8位的值,我需要移位至少16位的值才能得到下一个字符中的位。real\u buffer只是一个字符*,但它不代表ascii值,只代表二进制数据。写入uint16\u似乎是最好的方法。而不是memcpy我将使用双字节缓冲区=实缓冲区[n]感谢您的回答,仅供参考,尝试提取的值可以小于8位。我明白了…位数是可变的。感谢您的回答,仅供参考,尝试提取的值可以小于8位。我明白了…位数是可变的。这支持最大32位。OP寻求一个通用解决方案对于任意长度的数组。实际上不需要64位+的通用解决方案在不了解用例的情况下如何判断?@ilmiacs因为它可以很容易地用较小的数据块完成,并且C目前不支持任何大于64位的数据。这支持最大32位。OP寻求任意长度数组的通用解决方案。通用解决方案实际上不需要为64位+启用。在不了解用例的情况下,您如何判断?@ilmiacs,因为它很容易用较小的块完成,并且C目前不支持任何大于64位的数据
0xC9, 0xED, 0xED
0xC9, 0xED, 0xDB
0xC9, 0xED, 0xB7
0xC9, 0xED, 0x6E
0xC9, 0xED, 0xDC
0xC9, 0xED, 0xB9
0xC9, 0xED, 0x72
0xC9, 0xED, 0xE4
0xC9, 0xED, 0xC9
1110111000010110100001100010111010100110011011101010011001001110
            0110100001100010111010100110011011
#include <stdint.h>
#include <stdio.h>

uint32_t extractBytes(void *val, unsigned startBit, unsigned nBits)
{
    uint32_t *v32 = val;
    uint32_t mask = (1 << nBits) - 1;

    return (*v32 >> startBit) & mask;
}

int main()
{
    uint32_t x = 0b111101000;

    printf("0x%x\n", extractBytes(&x, 3, 4));
}