Pregunta

¿Cómo puedo convertir el siguiente struct a 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
¿Fue útil?

Solución

No se puede utilizar un static_cast aquí ya que no hay relación entre los tipos. Usted tendría que utilizar reinterpret_cast.

Básicamente, un static_cast se debe utilizar en la mayoría de los casos, mientras que reinterpret_cast probablemente debería hará la pregunta de por qué están haciendo de esta manera.

Este es un momento en el que usaría static_cast:

class Base {
};

class Derived : Base {
};

Base* foo = new Derived;
Derived* dfoo = static_cast<Derived*>( foo );

Mientras que aquí es donde es probable que necesite un reinterpret_cast:

void SetWindowText( WPARAM wParam, LPARAM lParam )
{
   LPCTSTR strText = reinterpret_cast<LPCTSTR>( lParam );
}

Otros consejos

Debido a las diferencias de embalaje estructura, no se puede hacer esto de forma fiable y sin portable, ya sea usando una matriz para empezar o escribir un código que llenó una nueva matriz de uno en uno de los miembros de la estructura por su nombre. Un reinterpret_cast podría funcionar en un compilador / plataforma / versión y romper en otra.

Es mejor que la asignación de una matriz en el montón o pila, y luego llenarlo uno por uno.

Trate reinterpret_cast<unsigned char*>. static_cast es para la conversión entre tipos compatibles, como una clase base a una clase derivada. reinterpret_cast es para lances entre los tipos no relacionados.

¿Por qué utilizar una extraña estructura en lugar de como:

unsigned uc char [5];

que luego se puede abordar de forma individual como uc [0], uc [1], uc [2], uc [3], uc [4] y por el puntero a la agregación (es de suponer lo que quiera con unsigned char *) con sólo "UC".

Parece mucho más simple de una estructura con múltiples miembros de char sin signo que se numeran en los nombres de los miembros (y por cierto, ¿qué pasó a UC4 -. Otro error de la solución matriz evitaría)

¿Qué hay de simplemente:

unsigned char * uc_ptr2 = &uc_ptr->uc1;

La manera más segura más portátil para convertir POD (es decir, C estructuras compatibles) tipos de punteros unsigned char no es mediante el uso de reinterpret_cast pero mediante el uso de static_cast (C ++ 0x correcciones de esta y faculta reinterpret_cast tener sin ambigüedad la misma semántica portátiles como la siguiente línea de código):

unsigned char *uc_ptr2 = static_cast<unsigned char*>(static_cast<void*>(uc_ptr));

Sin embargo, para todos los propósitos prácticos, a pesar de que el estándar de C ++ 03 se cree que es un tanto ambigua sobre el tema (no tanto al convertir los punteros de tipos de clase, pero cuando la conversión de punteros de tipo no-clase a 'unsigned char * '), la mayoría de las implementaciones harán lo correcto si utiliza reinterpret_cast como así:

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

Sospecho que debe estar bien con problemas de alineación ya que su estructura contiene caracteres sin signo que puede alinearse en cualquier byte, por lo que el compilador no se introduzca ningún embalaje entre los miembros (pero estrictamente hablando, esto depende de la implementación, por lo tenga cuidado).

En este caso, fundición con reinterpret_cast a unsigned char* está garantizado para trabajar y apuntará al primer miembro de datos unsigned char, debido a que su tipo es la denominada estructura POD (más o menos, una estructura C).

Cita de la Norma (de 9.2/17, si usted quiere ver)

  

Un puntero a un objeto de POD-struct, adecuadamente convertido usando un reinterpret_cast, apunta a su miembro inicial (o si ese miembro es un campo de bits, a continuación, a la unidad en la que reside) y viceversa. [Nota: Existe por lo tanto podría ser el relleno no identificado dentro de un objeto POD-estructura, pero no en su comienzo, si es necesario para lograr la alineación adecuada. ]

Así las siguientes obras

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

¿Quieres convertir la dirección de la estructura de una dirección de un unsigned char (como algunas de las respuestas a suponer) o la estructura real de un puntero (como se indica su pregunta)? En el primer caso, aquí hay algunas posibilidades:

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;

En este último caso, se puede utilizar uno de:

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;

Una opción es hacer a la inversa. Crear su "unsigned char *" buffer primero y luego utilizar la colocación de nuevo para asignar el objeto en la parte superior de este buffer.

#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;
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top