我有一个 std::uint8_t * bytes
成员 (ByteArray#bytes
),但不能将 T
值放在它正确。到目前为止,我只测试了在索引 0
处写入 int = 259
,然后我读取它并得到 3
作为输出。
ByteArray.hh
/*
* Copyright (c) 2017 Uncloud Group. All Rights Reserved.
*
* See ~/COPYRIGHT.md.
*/
#ifndef mutils_ByteArray_hh
#define mutils_ByteArray_hh
#include <cstddef>
#include <cstdint>
#include <cstdlib>
// (Endianness is detected at compile time, so...)
// (careful.)
#if __BYTE_ORDER == __LITTLE_ENDIAN
#define MUTILS_LE
#endif
static std::uint8_t * reversing;
static std::uint8_t i;
static std::uint8_t j;
namespace mutils
{
// Dynamically-sized array of bytes.
class ByteArray
{
public:
// (Creates an empty ByteArray.)
ByteArray() { SetLength(0); }
ByteArray(std::size_t length)
{
bytes = nullptr;
SetLength(length);
}
~ByteArray()
{
std::free(bytes);
}
// Read little-endian value.
template<typename T>
inline T
ReadLE(std::size_t index)
{
std::uint8_t s = bytes[index];
#ifdef MUTILS_LE
return T(s);
#else
return reverse<T>(&s);
#endif
}
// Write value using little-endianness.
// Note: No out-of-bounds check is done.
template<typename T>
inline void
WriteLE(std::size_t index, T value)
{
#ifndef MUTILS_LE
value = reverse(&value);
#endif
((T&) bytes[index]) = value;
}
inline auto
GetLength() { return length; }
void
SetLength(std::size_t len);
// ByteArray
// SliceView(std::size_t start_v, std::size_t end_v);
private:
std::uint8_t * bytes;
std::size_t length;
// Reverse the byte-order of a value.
template<typename T>
T
reverse(std::uint8_t * value)
{
for (i = 0, j = sizeof(T); (--j) >= sizeof(T); ++i)
reversing[j] = value[i];
return T(*reversing);
}
};
} // namespace mutils
#endif // mutils_ByteArray_hh
ByteArray.cc
/*
* Copyright (c) 2017 Uncloud Group. All Rights Reserved.
*
* See ~/COPYRIGHT.md.
*/
#include <mutils/ByteArray.hh>
#include <cstddef>
#include <cstdint>
#include <cstdlib>
// Updates the array length.
void
mutils::ByteArray::SetLength(std::size_t len)
{
if (len == 0)
bytes = nullptr;
else bytes = (std::uint8_t *) realloc(bytes, len);
length = len;
}
测试
#include <iostream>
int main()
{
mutils::ByteArray b(4);
b.WriteLE<int>(0, 259);
std::cout << b.ReadLE<int>(0) << "\r\n";
return 0;
}
最佳答案
这就是 memcpy
的用途。
将T t
写入bytes
:
memcpy(bytes + index, &t, sizeof t);
从bytes
中读取T
T result;
memcpy(&result, bytes + index, sizeof result);
return result;
如果字节顺序错误,则在字节数组中反转字节。更改 T
类型变量内的字节顺序可能会暂时创建非法表示并触发处理器错误。
您在 WriteLE
中使用的指针转换等其他方法也可能触发处理器错误,例如由于对齐。
只需使用memcpy
。
(即使是 std::copy
或 std::copy_n
在涉及到严格的别名和按位图像时也有点问题,3.9 节中的标准使用 std::memcpy
正是为了这个目的)
关于c++ - 使用 T 写入 uint8_t,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46548370/