Domanda

Come posso convertire il seguente 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
È stato utile?

Soluzione

Non è possibile utilizzare un static_cast qui poiché non v'è alcuna relazione tra i tipi. Si dovrà utilizzare reinterpret_cast.

In sostanza, una static_cast dovrebbe essere utilizzato nella maggior parte dei casi, mentre reinterpret_cast dovrebbe probabilmente farà questione perché si sta facendo in questo modo.

Qui è un momento in cui si usa static_cast:

class Base {
};

class Derived : Base {
};

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

considerando che qui è dove si sarebbe probabilmente bisogno di un reinterpret_cast:

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

Altri suggerimenti

A causa delle differenze di imballaggio struct, non si può fare questo in modo affidabile e portabile senza né utilizzando una matrice per cominciare o scrivere del codice che ha riempito un nuovo array uno alla volta dai membri struct per nome. Un reinterpret_cast potrebbe funzionare su un compilatore / platform / versione e rompere su un altro.

È meglio allocare una matrice sul mucchio o una pila, e poi riempire uno per uno.

Prova reinterpret_cast<unsigned char*>. static_cast è per la conversione tra tipi compatibili, come una classe base a una classe derivata. reinterpret_cast è per calchi tra tipi indipendenti.

Perché utilizzare una strana struct invece che come:

unsigned char uc [5];

che è quindi possibile affrontare singolarmente come uc [0], uc [1], uc [2], uc [3], uc [4] e dal puntatore alla aggregazione (presumibilmente quello che vuoi con unsigned char *) semplicemente "UC".

Sembra molto più semplice di una struttura con più membri unsigned char che sono numerati nei nomi dei membri (e btw, cosa è successo a UC4 -?. Un altro errore la soluzione matrice eviterebbe)

Che ne dite semplicemente:

unsigned char * uc_ptr2 = &uc_ptr->uc1;

Il modo più sicuro più portatile per convertire POD (ad esempio C le strutture compatibili) tipi di puntatori char unsigned non è quello di utilizzare reinterpret_cast ma utilizzando static_cast (C ++ 0x consente la correzione e autorizza reinterpret_cast di avere in modo inequivocabile la stessa semantica portatili come la seguente riga di codice):

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

Ma a tutti gli effetti, anche se lo standard C ++ 03 è pensato per essere un po 'ambigua sulla questione (non tanto durante la conversione puntatori di tipi di classe, ma durante la conversione puntatori di tipo non-classe per 'unsigned char * '), la maggior parte delle implementazioni fare la cosa giusta se utilizzati reinterpret_cast come:

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

Ho il sospetto che si dovrebbe andare bene con problemi di allineamento dal tuo struct contiene caratteri senza segno che possono essere allineati in ogni byte, in modo che il compilatore non inserire alcun imballaggio tra i membri (ma a rigor di termini, questo è carico di attuazione, in modo da usare cautela).

In questo caso, la fusione con reinterpret_cast per unsigned char* è garantito per funzionare e punterà al primo membro di dati unsigned char, perché il tipo è un cosiddetto struct POD (grosso modo, un C struct).

Citazione del standard (da 9.2/17, se vuoi guardare)

  

Un puntatore a un oggetto POD-struct, opportunamente trasformato utilizzando un reinterpret_cast, indica al suo membro iniziale (o se tale elemento è un campo di bit, quindi all'unità in cui risiede) e viceversa. [Nota: Ci potrebbe pertanto imbottitura senza nome di un oggetto POD-struct, ma non al suo inizio, come necessario per raggiungere appropriato allineamento. ]

Quindi, i seguenti lavori

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

Vuoi convertire l'indirizzo della struct a un indirizzo di un unsigned char (come alcune delle risposte assumere) o struct reale a un puntatore (come la tua domanda indica)? Nel primo caso, qui ci sono alcune possibilità:

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;

In quest'ultimo caso, è possibile utilizzare uno dei seguenti:

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 possibilità è quella di fare il contrario. Crea il tuo "unsigned char *" buffer prima e poi utilizzare nuova collocazione per allocare l'oggetto in cima a questo 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;
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top