使用 T 写入uint8_t
Write to an uint8_t using T
我有一个std::uint8_t * bytes
成员(ByteArray#bytes
),但无法正确放置T
值。到目前为止,我只测试了在索引0
处编写int = 259
,然后我读取它并得到3
作为输出。
http://rextester.com/HKU93771
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) << "rn";
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
)
发布示例来证明如何逆转原始类型(如unsigned
、float
和double
)的字节序没有问题,而不是结构体和等等。
下面的输入将只转储写在各个大小端序上的34.5555555559
值(在 ECMAScript 中表示为double
AFAIK)的字节
。(注意:float64
在 ES6 中表示为double
。
{
const arr = new DataView(new ArrayBuffer(16));
const byte = x =>
{
x = x.toString(16).toUpperCase();
return '#' + ((x.length - 1) ? x : `0${x}`);
};
const dump = size =>
{
const _arr = [];
for (let i = 0; i < size; ++i)
_arr.push(byte( arr.getUint8(i) ));
return _arr.join(' ');
};
arr.setFloat64(0, 34.5555555559, false);
console.log(`Big-endian: ${ dump(8) }`);
arr.setFloat64(0, 34.5555555559, true);
console.log(`Little-endian: ${ dump(8) }`);
}
输出:
大端序: #40 #41 #47 #1C #71#C7 #D9 #CE
小端序: #CE #D9 #C7 #71 #1C #47 #41 #40
所以你可以注意到字节只在小端序中被颠倒了。位上没有区别。在我的代码中,只有当编译器目标基于大端序时,我才必须反转字节。所以这就是float
字节序的工作方式,我想。
相关文章:
- 写入向量<向量<bool>>
- 如何将内容数组写入文本文件?
- 写入位置0x0000000C时发生访问冲突
- 使用ios:ate写入到流会覆盖现有文件
- 独立读取-修改-写入顺序
- 为什么在某些情况下不写入此文件?
- 用C++将哈希表写入文件并从文件中恢复
- std::当在256字节边界上写入整数时,流的奇怪行为
- 为什么指针不写入类的地址?
- 如何打开并写入一个名称取自C++中字符串的文件
- 从值小于256的uint16到uint8的Endian安全转换
- 如何在C++中从文件中读取/写入多个对象
- 链表中写入访问冲突的未知原因
- 着色器纹理值与创建纹理时写入的值不同
- MESI协议和std::atomic-它是否确保所有写入立即对其他线程可见?
- 在C++中一次将矢量值写入多个文件
- 当字段可以为null时,如何使用C++接口在Avro中写入数据
- 写入文件会产生一个空文件或根本没有文件
- std::带有自定义缓冲区的 iostream 不允许我写入
- 在 C++ 中使用指针将对象写入文件