memcpy 是将 float 打包成 uint32 的标准方法吗?
Is memcpy the standard way to pack float into uint32?
以下是将浮点数的位打包到 uint32 中的最佳方法吗?是的,这可能是一种快速而简单的方法,但我想确保没有更好的方法,或者在进程之间交换值不会引入奇怪的问题。
"Best" 在我的例子中,它永远不会在兼容的 C++ 编译器上中断(给定静态断言),可以在同一台计算机上的两个进程之间打包和解包,并且就像与将 uint32 复制到另一个 uint32 一样快。
进程A:
static_assert(sizeof(float) == sizeof(uint32) && alignof(float) == alignof(uint32), "no");
...
float f = 0.5f;
uint32 buffer[128];
memcpy(buffer + 41, &f, sizeof(uint32)); // packing
进程 B:
uint32 * buffer = thisUint32Is_ReadFromProcessA(); // reads "buffer" from process A
...
memcpy(&f, buffer + 41, sizeof(uint32)); // unpacking
assert(f == 0.5f);
是的,这是进行类型双关的标准方法。 memcpy
上的 Cppreferences 页面甚至包含一个示例,展示了如何使用它将 double
重新解释为 int64_t
#include <iostream>
#include <cstdint>
#include <cstring>
int main()
{
// simple usage
char source[] = "once upon a midnight dreary...", dest[4];
std::memcpy(dest, source, sizeof dest);
for (char c : dest)
std::cout << c << '\n';
// reinterpreting
double d = 0.1;
// std::int64_t n = *reinterpret_cast<std::int64_t*>(&d); // aliasing violation
std::int64_t n;
std::memcpy(&n, &d, sizeof d); // OK
std::cout << std::hexfloat << d << " is " << std::hex << n
<< " as an std::int64_t\n";
}
ouput
o
n
c
e
0x1.999999999999ap-4 is 3fb999999999999a as an std::int64_t
只要断言通过(您写入和读取的字节数正确),操作就是安全的。你不能把一个64位的对象打包成一个32位的对象,但是你可以把一个32位的对象打包成另一个32位的对象,只要它们是trivially copyable
或者这样:
union TheUnion {
uint32 theInt;
float theFloat;
};
TheUnion converter;
converter.theFloat = myFloatValue;
uint32 myIntRep = converter.theInt;
我不知道这是否更好,但这是另一种看待它的方式。
以下是将浮点数的位打包到 uint32 中的最佳方法吗?是的,这可能是一种快速而简单的方法,但我想确保没有更好的方法,或者在进程之间交换值不会引入奇怪的问题。
"Best" 在我的例子中,它永远不会在兼容的 C++ 编译器上中断(给定静态断言),可以在同一台计算机上的两个进程之间打包和解包,并且就像与将 uint32 复制到另一个 uint32 一样快。
进程A:
static_assert(sizeof(float) == sizeof(uint32) && alignof(float) == alignof(uint32), "no");
...
float f = 0.5f;
uint32 buffer[128];
memcpy(buffer + 41, &f, sizeof(uint32)); // packing
进程 B:
uint32 * buffer = thisUint32Is_ReadFromProcessA(); // reads "buffer" from process A
...
memcpy(&f, buffer + 41, sizeof(uint32)); // unpacking
assert(f == 0.5f);
是的,这是进行类型双关的标准方法。 memcpy
上的 Cppreferences 页面甚至包含一个示例,展示了如何使用它将 double
重新解释为 int64_t
#include <iostream> #include <cstdint> #include <cstring> int main() { // simple usage char source[] = "once upon a midnight dreary...", dest[4]; std::memcpy(dest, source, sizeof dest); for (char c : dest) std::cout << c << '\n'; // reinterpreting double d = 0.1; // std::int64_t n = *reinterpret_cast<std::int64_t*>(&d); // aliasing violation std::int64_t n; std::memcpy(&n, &d, sizeof d); // OK std::cout << std::hexfloat << d << " is " << std::hex << n << " as an std::int64_t\n"; }
ouput
o n c e 0x1.999999999999ap-4 is 3fb999999999999a as an std::int64_t
只要断言通过(您写入和读取的字节数正确),操作就是安全的。你不能把一个64位的对象打包成一个32位的对象,但是你可以把一个32位的对象打包成另一个32位的对象,只要它们是trivially copyable
或者这样:
union TheUnion {
uint32 theInt;
float theFloat;
};
TheUnion converter;
converter.theFloat = myFloatValue;
uint32 myIntRep = converter.theInt;
我不知道这是否更好,但这是另一种看待它的方式。