动态类型转换为变量类型

Dynamic type cast to the variable type

假设,我有一个 class,比如:

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));

但我也想避免为像 1-4 字节长整数(我有)这样的简单类型调用函数,因为简单赋值可以编译为单个 CPU 指令。请指教,实现这个的c++方法是什么?

谢谢!

你可以有类似这样的代码:

template<typename T>
void mymemcopy(T* a, void* b) {
    memcpy((void*)a, b, sizeof(T));
}

template<typename T>
constexpr void mymemcopy(T** a, void* b) {
    *a = static_cast<T*>(b);
}

constexpr void mymemcopy(int* a, void* b) {
    *a = *(int*)b;
}

constexpr void mymemcopy(unsigned char* a, void* b) {
    *a = *(unsigned char*)b;
}

int main()
{
    int a, b =10;
    mymemcopy(&a, &b);

    double a1, b1 =10;
    mymemcopy(&a1, &b1);

    unsigned char a2, b2 =10;
    mymemcopy(&a2, &b2);

    unsigned char *a3, *b3 =nullptr;
    mymemcopy(&a3, &b3);
}

我以某种方式认为您的案例用于嵌入式编程,我不是专家。我知道在嵌入式编程中你需要减少内存使用和代码。但是你问的会明显增加代码量。

memcpy 被每个现代 C++ 编译器完全理解,并且不会有一个实际的函数调用,除非你获取它的地址,将其存储在一个指针中,然后足够混淆编译器以至于它没有不再知道指针指向 memcpy.

或者,你知道的,关闭优化。

memcpy((void*)&a.f1, (void*)&memory[someAddress], sizeof(A::f1));

这里既没有理由转换为 void*,也没有使用危险的 C 风格转换。

std::memcpy(&a.f1, &memory[someAddress], sizeof(a.f1));

这是一种符合标准的方法,可以将表示与 a.f1 相同类型的数据的内存移动到 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) );
}

我在上面的实例中将其作为替代方案包含在内。