2

如何将以下内容转换structunsigned 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
4

9 回答 9

7

您不能在static_cast此处使用 a ,因为类型之间没有关系。您将不得不使用reinterpret_cast.

基本上, astatic_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 );
}
于 2009-07-08T04:06:43.447 回答
4

由于 struct 打包差异,如果不使用数组开头或编写一些代码,一次从 struct 成员中按名称填充一个新数组,则无法可靠且可移植地执行此操作。reinterpret_cast 可能在一个编译器/平台/版本上工作,而在另一个编译器/平台/版本上中断。

您最好在堆或堆栈上分配一个数组,然后一个一个地填充它。

于 2009-07-08T04:25:50.460 回答
2

试试reinterpret_cast<unsigned char*>static_cast用于在兼容类型之间进行转换,例如基类到派生类。reinterpret_cast用于不相关类型之间的强制转换。

于 2009-07-08T04:06:07.957 回答
1

你为什么要使用这样一个奇怪的结构而不是:

无符号字符 uc[5];

然后您可以单独将其寻址为 uc[0]、uc[1]、uc[2]、uc[3]、uc[4] 并通过指向聚合的指针(大概是您想要的 unsigned char *),只需“ uc”。

似乎比具有多个在成员名称中编号的 unsigned char 成员的结构简单得多(顺便说一句,uc4 发生了什么? - 数组解决方案将避免的另一个错误。)

于 2009-07-08T04:16:16.220 回答
1

简单地说:

unsigned char * uc_ptr2 = &uc_ptr->uc1;
于 2009-07-08T04:53:20.683 回答
1

将 POD(即与 C 兼容的结构)类型转换为无符号字符指针的最安全、最可移植的方法不是使用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);

我怀疑你应该对对齐问题没问题,因为你的结构包含可以在任何字节对齐的无符号字符,所以编译器不会在成员之间插入任何包装(但严格来说,这是依赖于实现的,所以要小心) .

于 2009-07-08T04:54:01.370 回答
1

在这种情况下,使用reinterpret_castto 进行强制转换unsigned char*可以保证工作并将指向第一个unsigned char数据成员,因为您的类型是所谓的 POD 结构(大致是 C 结构)。

标准报价(来自9.2/17,如果你想看的话)

使用 reinterpret_cast 适当转换的指向 POD 结构对象的指针指向其初始成员(或者如果该成员是位字段,则指向它所在的单元),反之亦然。[注意:因此,在 POD 结构对象中可能存在未命名的填充,但不是在其开头,这是实现适当对齐所必需的。]

所以以下工作

unsigned char * uc_ptr2 = reinterpret_cast<unsigned char*>(uc_ptr);
于 2009-07-08T05:18:16.530 回答
0

您要将结构的地址转换为无符号字符的地址(如某些答案所假设的那样)还是将实际的结构转换为指针(如您的问题所示)?如果是前者,这里有几种可能性:

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;
于 2009-07-08T06:01:57.863 回答
0

一种选择是反过来。首先创建您的“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;
}
于 2009-07-08T10:34:53.583 回答