将零件数组转换为一个字节数组

发布于 2025-02-04 02:37:42 字数 210 浏览 4 评论 0原文

我想将值为1s和0s的位阵列(bool* bitarray)转换为一个字节数组(无符号char* bytearray),其中每个索引处的值将是一个字节。 对于ex,索引0〜7在bitarray中将进入bytearray [1]。

我该怎么做?假设我已经有一系列位(但是金额可能会根据传入数据的变化)。 我并不担心将其排出8,因为我只会在Bitarray结束时添加填充物,以使其可将其排除在8。

I want to convert an array of bits (bool* bitArray) where the values are 1s and 0s into an array of bytes (unsigned char* byteArray) where the values at each index would be one byte.
For ex, index 0~7 in bitArray would go into byteArray[1].

How would I go about doing this? Assuming that I already have an array of bits (but the amount would be subject to change based on the incoming data).
I am not worried about having it divisible by 8 because I will just add padding at the end of the bitArray to make it divisible by 8.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

野稚 2025-02-11 02:37:42

只需使用位移动或查找数组,然后将数字与1位组合在一起,每个设置一个位于钻头或一次进行8位

int main() {
    bool input[] = {
        false, false, false, true, true, true, false, false, false,
        false, false, false, true, true, true, false, false, false,
        false, false, false, true, true, true, false, false, false,
        false, false, false, true, true, true, false, false, false,
    };

    constexpr auto len = sizeof(input) / sizeof(*input);
    constexpr size_t outLen = ((len % 8 == 0) ? 0 : 1) + len / 8;

    uint8_t out[outLen];

    bool* inPos = input;
    uint8_t* outPos = out;

    size_t remaining = len;

    // output bytes where there are all 8 bits available
    for (; remaining >= 8; remaining -= 8, ++outPos)
    {
        uint8_t value = 0;
        for (size_t i = 0; i != 8; ++i, ++inPos)
        {
            if (*inPos)
            {
                value |= (1 << (7 - i));
            }
        }
        *outPos = value;
    }

    if (remaining != 0)
    {
        // output byte that requires padding
        uint8_t value = 0;
        for (size_t i = 0; i != remaining; ++i, ++inPos)
        {
            if (*inPos)
            {
                value |= (1 << (7 - i));
            }
        }
        *outPos = value;
    }

    for (auto v : out)
    {
        std::cout << static_cast<int>(v) << '\n';
    }

    return 0;
}

。以下数组,如果您认为更简单地理解:

constexpr uint8_t Bits[8]
{
    0b1000'0000,
    0b0100'0000,
    0b0010'0000,
    0b0001'0000,
    0b0000'1000,
    0b0000'0100,
    0b0000'0010,
    0b0000'0001,
};

...
value |= Bits[i];
...

Just just use bit shifts or a lookup array and and combine numbers with 1 bit set each with bitwise or for 8 bits at a time:

int main() {
    bool input[] = {
        false, false, false, true, true, true, false, false, false,
        false, false, false, true, true, true, false, false, false,
        false, false, false, true, true, true, false, false, false,
        false, false, false, true, true, true, false, false, false,
    };

    constexpr auto len = sizeof(input) / sizeof(*input);
    constexpr size_t outLen = ((len % 8 == 0) ? 0 : 1) + len / 8;

    uint8_t out[outLen];

    bool* inPos = input;
    uint8_t* outPos = out;

    size_t remaining = len;

    // output bytes where there are all 8 bits available
    for (; remaining >= 8; remaining -= 8, ++outPos)
    {
        uint8_t value = 0;
        for (size_t i = 0; i != 8; ++i, ++inPos)
        {
            if (*inPos)
            {
                value |= (1 << (7 - i));
            }
        }
        *outPos = value;
    }

    if (remaining != 0)
    {
        // output byte that requires padding
        uint8_t value = 0;
        for (size_t i = 0; i != remaining; ++i, ++inPos)
        {
            if (*inPos)
            {
                value |= (1 << (7 - i));
            }
        }
        *outPos = value;
    }

    for (auto v : out)
    {
        std::cout << static_cast<int>(v) << '\n';
    }

    return 0;
}

The rhs of the |= operator could also be replaced with a lookup in the following array, if you consider this simpler to understand:

constexpr uint8_t Bits[8]
{
    0b1000'0000,
    0b0100'0000,
    0b0010'0000,
    0b0001'0000,
    0b0000'1000,
    0b0000'0100,
    0b0000'0010,
    0b0000'0001,
};

...
value |= Bits[i];
...

穿透光 2025-02-11 02:37:42

您应该使用std :: bitset用于一系列布尔,或者std :: vector&lt; bool&gt;(如果是动态尺寸)。和std :: Array用于数组或再次std :: vector动态大小。我只在下面进行了静态大小,然后转换为和转换。

转换涉及应该是一个应该是纪念物的东西(在Little Endian或Unsigned Char类型上)的许多位变化和循环。 -O2的编译器输出不良。 -o3删除循环,to_array2变得有趣。 GCC几乎设法优化了它,Clang实际上将其降低到movzx eax,word ptr [rdi] https://godbolt.org/z/4chb8o81e

#include <array>
#include <bitset>
#include <climits>

template <typename T, std::size_t len>
constexpr std::bitset<sizeof(T) * CHAR_BIT * len> from_array(const std::array<T, len> &arr) {
    std::bitset<sizeof(T) * CHAR_BIT * len> res;
    std::size_t pos = 0;
    for (auto x : arr) {
        for(std::size_t i = 0; i < sizeof(T) * CHAR_BIT; ++i) {
            res[pos++] = x & 1;
            x >>= 1;
        }
    }
    return res;
}

template <typename T, std::size_t len>
constexpr std::array<T, (len + sizeof(T) * CHAR_BIT - 1) / (sizeof(T) * CHAR_BIT)> to_array(const std::bitset<len> &bit) {
    std::array<T, (len + sizeof(T) * CHAR_BIT - 1) / (sizeof(T) * CHAR_BIT)> res;
    T mask = 1;
    T t = 0;
    std::size_t pos = 0;
    for (std::size_t i = 0; i < len; ++i) {
        if (bit[i]) t |= mask;
        mask <<= 1;
        if (mask == 0) {
            mask = 1;
            res[pos++] = t;
            t = 0;
        }
    }
    if constexpr (len % (sizeof(T) * CHAR_BIT) != 0) {
        res[pos] = t;
    }
    return res;
}

std::bitset<16> from_array2(const std::array<unsigned char, 2> &arr) {
    return from_array(arr);
}

std::array<unsigned short, 1> to_array2(const std::bitset<16> &bits) {
    return to_array<unsigned short>(bits);
}

#include <iostream>

int main() {
    std::array<unsigned char, 2> arr{0, 255};
    std::bitset bits = from_array(arr);
    std::cout << bits << std::endl;

    std::bitset<16> bits2{0x1234};
    std::array<unsigned short, 1> arr2 = to_array<unsigned short>(bits2);
    std::cout << std::hex << arr2[0] << std::endl;
}

You should be using std::bitset for an array of bools, or std::vector<bool> if it's dynamically sized. And std::array for the array or again std::vector for dynamic size. I've only done static size below and conversion to and from.

Converting involves a lot of bit shifts and loops for something that should be a memcpy (on little endian or unsigned char types). The compiler output for -O2 is bad. -O3 removes the loop and to_array2 gets interesting. gcc nearly manages to optimize it, clang actually gets it down to movzx eax, word ptr [rdi]: https://godbolt.org/z/4chb8o81e

#include <array>
#include <bitset>
#include <climits>

template <typename T, std::size_t len>
constexpr std::bitset<sizeof(T) * CHAR_BIT * len> from_array(const std::array<T, len> &arr) {
    std::bitset<sizeof(T) * CHAR_BIT * len> res;
    std::size_t pos = 0;
    for (auto x : arr) {
        for(std::size_t i = 0; i < sizeof(T) * CHAR_BIT; ++i) {
            res[pos++] = x & 1;
            x >>= 1;
        }
    }
    return res;
}

template <typename T, std::size_t len>
constexpr std::array<T, (len + sizeof(T) * CHAR_BIT - 1) / (sizeof(T) * CHAR_BIT)> to_array(const std::bitset<len> &bit) {
    std::array<T, (len + sizeof(T) * CHAR_BIT - 1) / (sizeof(T) * CHAR_BIT)> res;
    T mask = 1;
    T t = 0;
    std::size_t pos = 0;
    for (std::size_t i = 0; i < len; ++i) {
        if (bit[i]) t |= mask;
        mask <<= 1;
        if (mask == 0) {
            mask = 1;
            res[pos++] = t;
            t = 0;
        }
    }
    if constexpr (len % (sizeof(T) * CHAR_BIT) != 0) {
        res[pos] = t;
    }
    return res;
}

std::bitset<16> from_array2(const std::array<unsigned char, 2> &arr) {
    return from_array(arr);
}

std::array<unsigned short, 1> to_array2(const std::bitset<16> &bits) {
    return to_array<unsigned short>(bits);
}

#include <iostream>

int main() {
    std::array<unsigned char, 2> arr{0, 255};
    std::bitset bits = from_array(arr);
    std::cout << bits << std::endl;

    std::bitset<16> bits2{0x1234};
    std::array<unsigned short, 1> arr2 = to_array<unsigned short>(bits2);
    std::cout << std::hex << arr2[0] << std::endl;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文