动态类型转换为变量类型
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) );
}
我在上面的实例中将其作为替代方案包含在内。
假设,我有一个 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) );
}
我在上面的实例中将其作为替代方案包含在内。