c - 将 64 个 bool 数组打包/解包到一个 uint64 中

标签 c arrays bit packing bit-packing

我遇到过这个 answer .

但我遇到了 2 个问题,我不确定如何调整它以打包 64 位(见下文),而且我无法解开它们。

这是我要打包的东西:

const int i = 1;
#define is_bigendian() ((*(char *) &i) == 0)

#define MAGIC (is_bigendian() ? 0x0102040810204080 : 0x8040201008040201)

inline uint8_t pack8b(bool *a) {
    uint64_t t = *((uint64_t *) a);
    return (MAGIC * t >> 56) & 0xFF;
}

uint32_t pack32b(bool *a) {
    return (pack8b(a + 0) << 24) | (pack8b(a + 8) << 16) |
           (pack8b(a + 16) << 8) | (pack8b(a + 24) << 0);
}

uint64_t pack64b(bool *a) {
    return ((uint64_t) pack32b(a) << 32) | pack32b(a + 32);
}

编辑:这是我到目前为止所拥有的,就像一个魅力,我愿意接受有关性能改进的建议:

uint64_t MAGIC() {
    static const int i = 1;
    // Takes of little / big endian
    bool bigEndian = ((*(char *) &i) == 0);
    return bigEndian ? 0x0102040810204080 : 0x8040201008040201;
}

uint8_t pack8b(bool *a) {
    uint64_t t = *((uint64_t *) a);
    return (MAGIC() * t >> 56) & 0xFF;
}

uint16_t pack16b(bool *a) {
    return ((uint16_t) pack8b(a + 0) << 8) | (pack8b(a + 8) << 0);
}

uint32_t pack32b(bool *a) {
    return ((uint32_t) pack16b(a + 0) << 16) | (pack16b(a + 16) << 0);
}

uint64_t pack64b(bool *a) {
    return ((uint64_t) pack32b(a + 0) << 32) | (pack32b(a + 32) << 0);
}

void unpack8b(bool *a, uint8_t v) {
    uint64_t mask = 0x8080808080808080ULL;
    *((uint64_t *) a) = ((MAGIC() * v) & mask) >> 7;
}

void unpack16b(bool *a, uint16_t v) {
    unpack8b(a + 0, v >> 8);
    unpack8b(a + 8, v >> 0);
}

void unpack32b(bool *a, uint32_t v) {
    unpack16b(a + 0, v >> 16);
    unpack16b(a + 16, v >> 0);
}

void unpack64b(bool *a, uint64_t v) {
    unpack32b(a + 0, v >> 32);
    unpack32b(a + 32, v >> 0);
}

最佳答案

您的解决方案对我有用,我在 tio 上用 gcc 对其进行了测试:Try it online!

解压 uint64_t 的最简单函数是:

void unpack64b(uint64_t num, bool* bit_field) {
    for (int i = 63; 0 <= i; i--) {
        bit_field[i] = num & 1;
        num = num >> 1;
    }
}

如果 bit_field 被初始化为全零,那么提前退出是可能的:

void unpack64b(uint64_t num, bool* bit_field) {
    for (int i = 63; num > 0; i--) {
        bit_field[i] = num & 1;
        num = num >> 1;
    }
}

对于32位和64位的打包,这不应该也知道字节序编码吗?

关于c - 将 64 个 bool 数组打包/解包到一个 uint64 中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61016073/

相关文章:

php - 将 PHP 数组转换为对象的 JSON 数组

python - 如何在 numpy 中创建递增的多维数组

c++ - 位域成员的大小?

c - 读一个C文件,多读一行,为什么?

C 短时间内自动返回一个值到 "getch"

c - 基本C链表语法错误

c++ - 如何直接获取 rand() 序列中的第 n 个数字而不必调用 rand() n 次?

ruby-on-rails - postgres 数组和 rails 4 erb

php - 找到最高设置位

sql-server - PostgreSQL 和 SQL Server 中 "length/values"数据类型的默认 "bit"是什么