是否可以std::vector<unsigned char>通过其数据指针操作 an ,就好像它是 的容器一样float?
这是一个编译和(似乎?)按需要运行的示例(GCC 4.8,C++11):
#include <iostream>
#include <vector>
int main()
{
std::vector<unsigned char> bytes(2 * sizeof(float));
auto ptr = reinterpret_cast<float *>(bytes.data());
ptr[0] = 1.1;
ptr[1] = 1.2;
std::cout << ptr[0] << ", " << ptr[1] << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
此代码段成功地从字节缓冲区写入/读取数据,就好像它是一个float. 从阅读有关 reinterpret_cast我担心这可能是未定义的行为。我对理解类型别名细节的信心太小,无法确定。
代码片段是否如上文所述的未定义行为?如果是这样,是否有另一种方法来实现这种字节操作?
不,这是不允许的。
C++ 不仅仅是“一堆字节”——编译器(以及更抽象的语言)被告知你有一个unsigned chars 的容器,而不是一个floats的容器。没有floats 存在,你不能假装它们存在。
您正在寻找的规则(称为严格别名)可以在 下找到[basic.lval]/8。
相反会起作用,因为允许(通过同一段落中的特殊规则)通过unsigned char*. 但是,在你的情况下,最快的安全和正确的方式来“搞定”一个float来自东西开始生活unsigned char是std::memcpy或std::copy字节数据到一个实际的float存在:
std::vector<unsigned char> bytes(2 * sizeof(float));
float f1, f2;
// Extracting values
std::memcpy(
reinterpret_cast<unsigned char*>(&f1),
bytes.data(),
sizeof(float)
);
std::memcpy(
reinterpret_cast<unsigned char*>(&f2),
bytes.data() + sizeof(float),
sizeof(float)
);
// Putting them back
f1 = 1.1;
f2 = 1.2;
std::memcpy(
bytes.data(),
reinterpret_cast<unsigned char*>(&f1),
sizeof(float)
);
std::memcpy(
bytes.data() + sizeof(float),
reinterpret_cast<unsigned char*>(&f2),
sizeof(float)
);
Run Code Online (Sandbox Code Playgroud)
只要这些字节float在您的系统上形成有效的表示,就可以了。诚然,它看起来有点笨拙,但快速的包装器功能将使它的工作变得简单。
假设您只关心floats 并且不需要可调整大小的缓冲区,一个常见的替代方法是生成一些std::aligned_storage然后在结果缓冲区中做一堆新的放置。从 C++17 开始,您也可以使用std::launder,尽管在这种情况下调整向量的大小(读取:重新分配其缓冲区)也是不可取的。
此外,这些方法非常复杂,会导致复杂的代码,并非所有读者都能理解。如果您可以清洗您的数据,使其“是”一系列floats,那么您不妨一开始就让自己变得友善std::vector<float>。根据上述内容,unsigned char*如果您愿意,可以获取和使用该缓冲区的 。
应该注意的是,在野外有很多代码使用您的原始方法(特别是在具有准系统 C 传统的旧项目中)。在许多实现中,它似乎有效。但是,人们普遍认为它是有效和/或安全的,如果您依赖它,您很容易“重新排序”(或其他优化)指令。
对于它的价值,如果您禁用严格别名(GCC 允许将其作为扩展,而 LLVM 甚至没有实现它),那么您可能可以摆脱原始代码。小心点。
| 归档时间: |
|
| 查看次数: |
123 次 |
| 最近记录: |