【问题标题】:Convert Integer to 4 byte ungisned char vector (in Big endian byte order)将 Integer 转换为 4 字节 ungisned char 向量(以 Big endian 字节顺序)
【发布时间】:2020-02-26 09:53:29
【问题描述】:

假设,我想以 4 个字节将十进制 31 写入二进制文件(已加载到向量中),所以我必须写为 00 00 00 1f,但我不知道如何将十进制数转换为十六进制字符串(4字节)

因此,无符号字符向量中的预期十六进制为:

0x00 0x00 0x00 0x1f // int value of this is 31

为此,我尝试了以下操作:

std::stringstream stream;
stream << std::setfill('0') << std::setw(sizeof(int) * 2) << std::hex << 31;
cout << stream.str();

输出:

0000001f

上面的代码行以字符串格式提供输出,但我希望它以“0x”格式转换为无符号字符向量,所以我的输出向量在转换后应该有元素为 0x00 0x00 0x00 0x1F。

【问题讨论】:

  • 你的问题是什么?像这样格式化还是获取向量中的值?
  • @Timo,我无法获取 unsigned char 向量中的值。
  • sizeof(int) 可能不会像您认为的那样做。今天在所有常见平台上都是4,所以你得到setw(8)
  • @hyde 这正是 OP 想要的。一个字节需要 2 个十六进制数字。因此,如果您想以十六进制显示int,则需要sizeof(int) * 2 数字。
  • “实际上假设,我想用 4 个字节将十进制 31 写入二进制文件”。如果你在二进制流中写入一个整数,这正是发生的情况。无需转换任何东西(给定正确的字节序)。

标签: c++


【解决方案1】:

不用担心endianness,您可以将int 值复制到适当大小的字符缓冲区中。这个缓冲区可以是向量本身。

大概是这样的:

std::vector<uint8_t> int_to_vector(unsigned value)
{
    // Create a vector of unsigned characters (bytes on a byte-oriented platform)
    // The size will be set to the same size as the value type
    std::vector<uint8_t> buffer(sizeof value);

    // Do a byte-wise copy of the value into the vector data
    std::memcpy(buffer.data(), &value, sizeof value);

    return buffer;
}

向量中的字节顺序将始终按照主机本机顺序。如果要求特定顺序,则需要使用按位运算将多字节值的每个字节复制到数组的特定元素中(不能使用std::memcpy)。

另外请注意,如果uint8_t 不是unsigned char 的别名,此函数将破坏严格的别名。而uint8_t 是可选类型,有些平台没有 8 位实体(尽管它们并不常见)。


对于特定于字节序的变体,其中一个字节的每个值被一个一个地提取并添加到向量中,可能是这样的:

std::vector<uint8_t> int_to_be_vector(unsigned value)
{
    // Create a vector of unsigned characters (bytes on a byte-oriented platform)
    // The size will be set to the same size as the value type
    std::vector<uint8_t> buffer(sizeof value);

    // For each byte in the multi-byte value, copy it to the "correct" place in the vector
    for (size_t i = buffer.size(); i > 0; --i)
    {
        // The cast truncates the value, dropping all but the lowest eight bits
        buffer[i - 1] = static_cast<uint8_t>(value);
        value >>= 8;
    }

    return buffer;
}

Example of it working

【讨论】:

  • 我们不能也直接memcpy到vector::data(假设向量已相应调整大小)?
  • @Timo 我不确定,考虑到严格的别名等等。我实际上不确定临时数组可以是uint8_t,还是必须是char
  • @Someprogrammerdude 和 @Timo 实际上 std::vector::data()T* 所以对于 astd::vector&lt;unsigned char&gt; 它应该是安全的(没有严格的混叠违规,对吗?)。
  • @Amogh 如前所述,我的函数不受字节序问题的困扰。改变字节顺序的一种简单方法是简单地反转向量。
  • @Amogh 错了,他想说这个函数将始终使用系统/平台字节序(因此,如果您的系统是小字节序,则为小字节序,否则为大字节序)。如果你想改变它,你可以像上面提到的那样反转向量。
【解决方案2】:

您可以使用循环每次提取原始数字的一个字节并将其存储在向量中。

#include <algorithm>
#include <cstdint>
#include <iostream>
#include <vector>

using u8 = std::uint8_t;
using u32 = std::uint32_t;

std::vector<u8> GetBytes(const u32 number) {
    const u32 mask{0xFF};
    u32 remaining{number};

    std::vector<u8> result{};
    while (remaining != 0u) {
        const u32 bits{remaining & mask};
        const u8 res{static_cast<u8>(bits)};
        result.push_back(res);
        remaining >>= 8u;
    }
    std::reverse(std::begin(result), std::end(result));
    return result;
}

int main() {
    const u32 myNumber{0xABC123};
    const auto bytes{GetBytes(myNumber)};
    std::cout << std::hex << std::showbase;
    for (const auto b : bytes) {
        std::cout << static_cast<u32>(b) << ' ';
    }
    std::cout << std::endl;
    return 0;
}

这个程序的输出是:

0xab 0xc1 0x23

【讨论】:

    猜你喜欢
    • 2010-10-16
    • 1970-01-01
    • 1970-01-01
    • 2022-12-12
    • 1970-01-01
    • 1970-01-01
    • 2012-10-09
    • 2019-09-18
    • 1970-01-01
    相关资源
    最近更新 更多