动态类型转换为变量类型
假设,我有一个类,例如:
struct A
{
uint8_t f1;
int16_t f2;
};
我需要从内存缓冲区数据中设置它的成员值,例如:
uint8_t * memory=device.getBufferedDataFromDevice();
A a;
a.f1=*((uint8_t*)&memory[someAddress]);
a.f2=*((int16_t*)&memory[someOtherAddress]);
但我想让它更灵活,并避免显式类型转换,以便有可能在不更改其余代码的情况下更改声明中的类型。当然,我可以通过以下方式实现它:
memcpy((void*)&a.f1, (void*)&memory[someAddress], sizeof(A::f1));
memcpy((void*)&a.f1, (void*)&memory[someAddress], sizeof(A::f1));
但我也想避免为简单类型调用函数,如 1-4 字节长整数(我有),因为简单的赋值可以编译为单个 CPU 指令。请指教,实现这一点的C++方式是什么?
谢谢!
回答
memcpy每个现代 C++ 编译器都完全理解memcpy.
或者,您知道,关闭优化。
这里既没有理由void*强制转换为,也没有理由使用危险的 C 风格转换。
std::memcpy(&a.f1, &memory[someAddress], sizeof(a.f1));
这是一种符合标准的方法来移动表示与a.f1over相同类型数据的内存a.f1,假设a.f1可以简单地复制。(注意我使用了相同的标记序列 -- a.f1-- 用于写入的内容和大小。)
编译器会将其优化为适当的程序集,并且不会有函数调用开销。
Live example,可以看到生成的程序集。
现在,您可能会反对“但不能保证!”。
C++ 标准不包括a+b不会作为循环实现的保证int r = 0; for (int i = 0; i < a; ++i){++r;} for (int i = 0; i < b; ++i){++r;}。
你不能假设你的 C++ 编译器是敌对的。
现有的 C++ 编译器优化了对memcpy. 编写代码假设它不会发生是浪费时间。
你也可以写一个稍微安全一点的memcpy
template<class Dest>
void memcpyT( Dest* dest, void const* src ) {
static_assert( std::is_trivially_copyable_v<Dest> );
memcpy( dest, src, sizeof(Dest) );
}
我在上面的示例中包含了它作为替代。
- @BbIKTOP 如果您认为 `memcpy(&a, &b, 7)` 明确告诉 C++ 使用链接,那您就错了。一种常见的误解是,您脑中在 C++ 程序代码到汇编之间的幼稚映射就是 C++ 的定义。它不是。C++ 标准库定义了编译单元,C++/C 标准库的主体不是编译单元,您的工具链如何工作的事实是标准之外的实现细节。C/C++ 标准描述了调用 `memcpy` 的作用,它没有解决它被链接或其他任何问题。