【问题标题】:Convert struct to unsigned char *将结构转换为无符号字符 *
【发布时间】:2009-07-08 04:02:53
【问题描述】:

如何将以下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

【问题讨论】:

    标签: c++ type-conversion static-cast


    【解决方案1】:

    你不能在这里使用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 );
    }
    

    【讨论】:

    • 在示例中,您提供要使用的转换应该是 dynamic_cast,因为存在继承关系。 static_cast 可以与不相关(从继承关系的角度)一起使用,例如将整数转换为枚举类型,将双精度类型转换为整数...
    • @Jared - 您实际上可以在这里使用 static_cast - 请参阅我的答案。 @dribeas - 这里没有 static_cast 很好 - dynamic_cast 实际上在这里不起作用,因为 Base 中没有虚函数 - 但如果有一个虚拟析构函数 - 可以使用任何一个强制转换 - static_cast 会更有效当然,虽然 dynamic_cast 有一定的运行时优势(在这种情况下不需要)
    【解决方案2】:

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

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

    【讨论】:

    • 我正要自己发布同样的内容。总是为这类事情编写打包/解包函数。
    • 您可能可以使用一些编译指示来控制打包,但这将是特定于编译器的。
    【解决方案3】:

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

    【讨论】:

    • 哇,你打败了我。比我早 35 秒 :)
    【解决方案4】:

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

    无符号字符 uc[5];

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

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

    【讨论】:

    • 我刚刚注意到缺少 uc4。我发布的示例是说明性的,我的结构具有一定的意义。还是谢谢。
    【解决方案5】:

    简单地说:

    unsigned char * uc_ptr2 = &uc_ptr->uc1;
    

    【讨论】:

      【解决方案6】:

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

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

      【讨论】:

        【解决方案7】:

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

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

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

        所以下面的作品

        unsigned char * uc_ptr2 = reinterpret_cast<unsigned char*>(uc_ptr);
        

        【讨论】:

          【解决方案8】:

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

          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;
          

          【讨论】:

            【解决方案9】:

            一种选择是做相反的事情。首先创建您的“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;
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2021-03-15
              • 2019-11-08
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2012-09-16
              相关资源
              最近更新 更多