将 struct 转换为 unsigned char *
-
11-09-2019 - |
题
我如何转换以下内容 struct
到 unsigned char*
?
typedef struct {
unsigned char uc1;
unsigned char uc2;
unsigned char uc3;
unsigned char uc5;
unsigned char uc6;
} uchar_t;
uchar_t *uc_ptr = new uchar;
unsigned char * uc_ptr2 = static_cast<unsigned char*>(*uc_ptr);
// invalid static cast at the previous line
解决方案
你不能使用 static_cast
因为类型之间没有关系。你必须使用 reinterpret_cast
.
基本上,一个 static_cast
大多数情况下应该使用,而 reinterpret_cast
可能会让你质疑为什么要这样做。
这是你会使用的时间 static_cast
:
class Base {
};
class Derived : Base {
};
Base* foo = new Derived;
Derived* dfoo = static_cast<Derived*>( foo );
而这里你可能需要一个 reinterpret_cast
:
void SetWindowText( WPARAM wParam, LPARAM lParam )
{
LPCTSTR strText = reinterpret_cast<LPCTSTR>( lParam );
}
其他提示
由于结构打包差异,如果不首先使用数组或编写一些代码来按名称从结构成员一次填充一个新数组,则无法可靠且可移植地完成此操作。reinterpret_cast 可能在一个编译器/平台/版本上工作,但在另一个编译器/平台/版本上可能会中断。
你最好在堆或栈上分配一个数组,然后一一填充它。
尝试 reinterpret_cast<unsigned char*>
. static_cast
用于在兼容类型之间进行转换,例如基类到派生类。 reinterpret_cast
用于不相关类型之间的转换。
为什么你会使用这样一个奇怪的结构而不是:
无符号字符uc[5];
然后您可以单独将其寻址为 uc[0]、uc[1]、uc[2]、uc[3]、uc[4] 并通过指向聚合的指针(大概是您想要的 unsigned char * )“ UC”。
看起来比具有多个在成员名称中编号的无符号 char 成员的结构简单得多(顺便说一句,uc4 发生了什么?-- 数组解决方案可以避免的另一个错误。)
简单来说怎么样:
unsigned char * uc_ptr2 = &uc_ptr->uc1;
最安全、最便携的 POD 转换方式(即C 兼容结构)类型到 unsigned char 指针不是通过使用 reinterpret_cast
但通过使用 static_cast
(C++0x 修复了这个问题,并授权 reinterpret_cast 明确具有与以下代码行相同的可移植语义):
unsigned char *uc_ptr2 = static_cast<unsigned char*>(static_cast<void*>(uc_ptr));
但出于所有实际目的,尽管 C++03 标准被认为在这个问题上有些含糊(在转换类类型的指针时不是那么多,但在将非类类型的指针转换为“unsigned char*”时) ,如果您确实使用,大多数实现都会做正确的事情 reinterpret_cast
如此:
unsigned char *uc_ptr2 = reinterpret_cast<void*>(uc_ptr);
我怀疑您应该可以解决对齐问题,因为您的结构包含可以在任何字节对齐的无符号字符,因此编译器不会在成员之间插入任何包装(但严格来说,这是依赖于实现的,因此请谨慎使用) 。
在这种情况下,铸造 reinterpret_cast
到 unsigned char*
保证可以工作并且会指向第一个 unsigned char
数据成员,因为您的类型是所谓的 POD 结构(大致为 C 结构)。
标准引用(来自 9.2/17
, ,如果你想看的话)
指向 POD 结构对象的指针(使用 reinterpret_cast 进行适当转换)指向其初始成员(或者如果该成员是位字段,则指向它所在的单元),反之亦然。[笔记:因此,POD 结构对象内可能存在未命名的填充,但在其开头不存在,这是实现适当对齐所必需的。]
所以下面的作品
unsigned char * uc_ptr2 = reinterpret_cast<unsigned char*>(uc_ptr);
您是否想将结构的地址转换为无符号字符的地址(如某些答案所假设的那样)或将实际结构转换为指针(如您的问题所示)?如果是前者,有以下几种可能性:
unsigned char * uc_ptr2 = static_cast<unsigned char *>(static_cast<void *>(uc_ptr));
unsigned char * uc_ptr2 = reinterpret_cast<unsigned char *>(uc_ptr);
unsigned char * uc_ptr2 = (unsigned char *)uc_ptr;
如果是后者,您可以使用以下之一:
unsigned char * uc_ptr2 = *static_cast<unsigned char **>(static_cast<void *>(uc_ptr));
unsigned char * uc_ptr2 = *reinterpret_cast<unsigned char **>(uc_ptr);
unsigned char * uc_ptr2 = *(unsigned char **)uc_ptr;
一种选择是反其道而行之。首先创建“unsigned char *”缓冲区,然后使用placement new 在此缓冲区顶部分配对象。
#include <iostream>
struct uchar_t {
unsigned char uc1;
unsigned char uc2;
unsigned char uc3;
unsigned char uc4;
unsigned char uc5;
unsigned char uc6;
};
int main ()
{
unsigned char * buffer
= new unsigned char[ sizeof (uchar_t)/sizeof (unsigned char) ];
uchar_t * uc = new (buffer) uchar_t ();
uc->uc3 = 'a';
std::cout << buffer[2] << std::endl;
delete buffer;
}