C++整数转字节数组

44

我有一个Java代码中的方法,它会根据给定的整数返回字节数组:

private static byte[] intToBytes(int paramInt)
{
     byte[] arrayOfByte = new byte[4];
     ByteBuffer localByteBuffer = ByteBuffer.allocate(4);
     localByteBuffer.putInt(paramInt);
     for (int i = 0; i < 4; i++)
         arrayOfByte[(3 - i)] = localByteBuffer.array()[i];
     return arrayOfByte;
}

有人能给我一些提示,如何将这个方法转换为C++?

10个回答

83

你不需要为此编写整个函数;一个简单的强制转换就足够了:

int x;
static_cast<char*>(static_cast<void*>(&x));

C++中的任何对象都可以被重新解释为一个字节数组。如果你想将这些字节复制到另一个单独的数组中,可以使用std::copy

int x;
char bytes[sizeof x];
std::copy(static_cast<const char*>(static_cast<const void*>(&x)),
          static_cast<const char*>(static_cast<const void*>(&x)) + sizeof x,
          bytes);

这两种方法都没有考虑字节顺序,但是因为你可以将 int 重新解释为字节数组,所以很容易自行执行任何必要的修改。


1
可能。不适用于英特尔计算机(或者至少不会得到相同的结果)。 - James Kanze
10
我很好奇:为什么你使用了两个static_cast<>而不是一个reinterpret_cast<> - PaulH
4
详细说明:大约一两年前在这里进行了长时间的讨论,讨论是否保证reinterpret_cast等效于一对static_cast。如果我记得正确,基本上认为两者都应该始终有效,但是所有内容都非常复杂,所以我仍然避免使用reinterpret_cast - James McNellis
1
这个方法的结果似乎取决于字节序。假设x=0x4142,在小端机器上运行此过程,迭代字节数组并打印每个字节,你会得到“BA”。如果你想得到“AB”,你必须自己反转结果。 - Yan
2
将int转换为字节数组是否定义良好?我认为像访问其他类型的对象一样访问对象是未定义的行为。 - Ayxan Haqverdili

33

使用 std::vector<unsigned char>

#include <vector>
using namespace std;

vector<unsigned char> intToBytes(int paramInt)
{
     vector<unsigned char> arrayOfByte(4);
     for (int i = 0; i < 4; i++)
         arrayOfByte[3 - i] = (paramInt >> (i * 8));
     return arrayOfByte;
}

6
这段Java代码生成的是大端字节顺序;而你生成的是小端字节顺序。建议使用移位计数作为循环控制:int i = 32; while (i != 0) {arrayOfByte[i] = paramInt >> i; i -= 8;} - James Kanze
1
@JamesKanze:等等……当arrayOfByte的值为[32, 24, 16, 8]时,你真的可以使用i来访问它吗?我认为你应该使用arrayOfByte[i/8] - Tomáš Zato
1
@TomášZato 是的;索引应该为i/8 - James Kanze

23

您可以使用与和移位操作获取单个字节:

byte1 =  nint & 0x000000ff
byte2 = (nint & 0x0000ff00) >> 8
byte3 = (nint & 0x00ff0000) >> 16
byte4 = (nint & 0xff000000) >> 24

13

我使用的另一种有用的方法是使用联合:

union byteint
{
    byte b[sizeof int];
    int i;
};
byteint bi;
bi.i = 1337;
for(int i = 0; i<4;i++)
    destination[i] = bi.b[i];

这将使得字节数组和整数“重叠”(共享相同的内存)。只要字节数组与类型大小相同(否则其中一个字段将不会受到另一个字段的影响),就可以使用所有类型进行此操作。而将它们作为一个对象也很方便,当你需要在整数操作和字节操作/复制之间切换时。


7
错误地读取联合体成员是未定义行为,也是对联合体的滥用。 - MateuszL
2
这是错误的。这不是联合的用途。这不是联合工作的方式。谬论! - Lightness Races in Orbit
3
在某些机器上,这个技巧非常聪明,但遗憾的是它不是标准用法,也是危险的。请参见此联合引用:"联合体大小仅需足以容纳其最大成员,其他数据成员分配在与该最大成员相同的字节中作为该最大成员的一部分。分配的细节是实现定义的,并且从未最近写入的联合成员中读取是未定义行为。许多编译器实现了作为非标准语言扩展的功能,即能够读取联合体的非活动成员。" - RoboticForest

8
std::vector<unsigned char> intToBytes(int value)
{
    std::vector<unsigned char> result;
    result.push_back(value >> 24);
    result.push_back(value >> 16);
    result.push_back(value >>  8);
    result.push_back(value      );
    return result;
}

8
一个int(或者任何其他数据类型)已经以字节形式存储在内存中。那为什么不直接复制内存呢?
memcpy(arrayOfByte, &x, sizeof x);

一条简洁优雅的命令,适用于任何其他数据类型。



如果需要反转字节,可以使用std::reverse

memcpy(arrayOfByte, &x, sizeof x);
std::reverse(arrayOfByte, arrayOfByte + sizeof x);

更好的方法是,最好一开始就将字节按相反的顺序复制

BYTE* p = (BYTE*) &x;
std::reverse_copy(p, p + sizeof x, arrayOfByte);

如果您不想完全复制数据,只需使用其字节表示即可。
BYTE* bytes = (BYTE*) &x;

6

整型与字节类型的相互转换。

unsigned char bytes[4];
unsigned long n = 1024;

bytes[0] = (n >> 24) & 0xFF;
bytes[1] = (n >> 16) & 0xFF;
bytes[2] = (n >> 8) & 0xFF;
bytes[3] = n & 0xFF;

printf("%x %x %x %x\n", bytes[0], bytes[1], bytes[2], bytes[3]);


int num = 0;
for(int i = 0; i < 4; i++)
 {
 num <<= 8;
 num |= bytes[i];
 }


printf("number %d",num);

3

我知道这个问题已经有了答案,但是我想提供我的解决方案。我使用的是模板函数和整数约束。

以下是我的解决方案:

#include <type_traits>
#include <vector>

template <typename T,
          typename std::enable_if<std::is_arithmetic<T>::value>::type* = nullptr>
std::vector<uint8_t> splitValueToBytes(T const& value)
{
    std::vector<uint8_t> bytes;

    for (size_t i = 0; i < sizeof(value); i++)
    {
        uint8_t byte = value >> (i * 8);
        bytes.insert(bytes.begin(), byte);
    }

    return bytes;
}

应该是唯一的答案,作为最普遍和无魔数解决方案。 - dimazava

0
return ((byte[0]<<24)|(byte[1]<<16)|(byte[2]<<8)|(byte[3]));

:D


4
他恰恰相反地提出了问题。 - BlackBear
5
哇,我失败了!总觉得如果我不立即回复,就会有数百万其他人回复。我是对的,但我想我应该确保理解问题,哈哈哈。 - jberg
是的,我也尽可能快地回答问题,有时候会写一些废话 ;) - BlackBear
1
它仍然有用。 - Jason Rice

0

我希望我的能帮到你

template <typename t_int>
std::array<uint8_t, sizeof (t_int)> int2array(t_int p_value) {
    static const uint8_t _size_of (static_cast<uint8_t>(sizeof (t_int)));
    typedef std::array<uint8_t, _size_of> buffer;
    static const std::array<uint8_t, 8> _shifters = {8*0, 8*1, 8*2, 8*3, 8*4, 8*5, 8*6, 8*7};

    buffer _res;
    for (uint8_t _i=0; _i < _size_of; ++_i) {
        _res[_i] = static_cast<uint8_t>((p_value >> _shifters[_i]));
    }
    return _res;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接