Domanda

Sto cercando di costruire cairomm per gtkmm su windows usando mingw.Compilazione rompe in una chiamata di funzione che ha un parametro che fa un reinterpret_cast di un bool void*.

cairo_font_face_set_user_data(cobj(), &USER_DATA_KEY_DEFAULT_TEXT_TO_GLYPHS, reinterpret_cast<void*>(true), NULL);

Questo è dove il codice si rompe, e la ragione è "invalid reinterpret_cast da bool void*".Perché succede questo e come posso modificare questa riga per farlo compilare?Bisogno di aiuto

È stato utile?

Soluzione

Io la vedo sia i dati dell'utente e si ha il controllo su ciò che viene fatto con il valore, il cast del bool int primo: reinterpret_cast<void *> (static_cast<int> (true)).Facendo questo senso che il void* parametro prende il posto del template, in questo ANSI-C biblioteca.Tutto ciò che serve è un valore true/false.Quindi, non ci dovrebbe essere alcun pericolo temporaneamente la codifica questo come un puntatore a lungo, come è ben documentato come tale.Davvero, si sarebbe meglio con questo: reinterpret_cast<void *> (1) o reinterpret_cast<void *> (+true).

Altri suggerimenti

Sembra che dovrebbe funzionare, secondo lo standard. La Sezione 3.9.1-7 dice che bool è un tipo integrale e 5.2.10-5 dice che un valore di tipo integrale può essere esplicitamente convertito in un puntatore usando reinterpret_cast. Sembra che il tuo compilatore non sia completamente standard.

Potresti cavartela cambiando il " true " a un 1? La conversione tra numeri interi e tipi di puntatore è una tradizione vecchia e disonorevole in C e quindi in C ++, e sarebbe sorprendente trovare un compilatore che non lo farebbe.

Oppure, se davvero devi farlo, prova (void *) true. Quindi lavati le mani.

reinterpret_cast è una una cattiva idea . Raccontaci di più sul problema che stai cercando di risolvere e forse troveremo una soluzione senza ricorrere alla reinterpretazione. Perché vuoi convertire bool in void *?

L'unico compilatore di cui mi lamento è GCC (MinGW con GCC 3.4.5) - e non sono sicuro del perché. Lo standard sembra indicare chiaramente che ciò è consentito:

  

3.9.1 Tipi fondamentali

     

...

     

Tipi bool, char, wchar_t e the   tipi interi con segno e senza segno sono   chiamati collettivamente tipi integrali.

     

5.2.10 Reinterpretare il cast:

     

...

     

Un valore di tipo integrale o   il tipo di enumerazione può essere esplicitamente   convertito in un puntatore.

Detto questo, soluzione alternativa di monjardin sull'uso reinterpret_cast<void *> (static_cast<int> (true)) o reinterpret_cast<void *> (1) sono soluzioni alternative ragionevoli.

Fallisce perché il cast non ha senso: stai prendendo un valore booleano vero / falso e stai chiedendo al compilatore di interpretarlo come un puntatore, che in termini schietti è una posizione di memoria. I due non sono nemmeno collegati in remoto.

Prova una versione più recente del tuo compilatore. Ho appena testato e questo cast funziona almeno su gcc 4.1 e versioni successive. Tuttavia, non so esattamente come le versioni di gcc si associno alle versioni di mingw.

In alcune situazioni, è altamente desiderabile che il compilatore avvisi o errore su codice come reinterpret_cast<void*>(true), anche se questo codice è apparentemente legale in C ++. Ad esempio, aiuta nel porting su piattaforme a 64 bit.

Trasmettere un puntatore a 64 bit in un tipo integrale che è più piccolo di un puntatore (come int o bool) è spesso un bug: stai troncando il valore del puntatore. Inoltre, la specifica C ++ non sembra garantire che puoi lanciare direttamente un puntatore in un tipo integrale più piccolo (enfasi aggiunta):

  

5.2.10.4. Un puntatore può essere esplicitamente convertito in qualsiasi tipo integrale abbastanza grande da tenerlo . La funzione di mappatura è definita dall'implementazione.

Allo stesso modo, il casting di un tipo integrale più piccolo in un puntatore a 64 bit (come con reinterpret_cast<void*>(static_cast<int>(true))) è spesso anche un bug: il compilatore deve riempire i bit superiori del puntatore con qualcosa; riempie zero o estende il segno? A meno che tu non stia scrivendo un codice specifico di piattaforma di basso livello per l'accesso I / O mappato in memoria o DMA, di solito non vuoi farlo affatto, a meno che tu non stia facendo qualcosa di strano (come inserire un booleano in un puntatore ). Ma la specifica C ++ non sembra dire molto su questo caso, a parte il fatto che è definita dall'implementazione (nota a piè di pagina omessa):

  

5.2.10.5. Un valore di tipo integrale o di enumerazione può essere convertito esplicitamente in un puntatore. *

     

Un puntatore convertito in un numero intero di dimensioni sufficienti (se presente nell'implementazione) e di nuovo allo stesso tipo di puntatore avrà il suo valore originale; i mapping tra puntatori e numeri interi sono altrimenti definiti dall'implementazione.

suggerito @monjardin void*. Se l'origine dell'errore era la mancata corrispondenza tra la dimensione del tipo integrale e la dimensione del puntatore, questo funzionerà sulla maggior parte delle piattaforme a 32 bit (dove sia uintptr_t che DWORD_PTR sono 32 bit) ma falliscono nella maggior parte dei 64 bit piattaforme (dove <=> è 32 bit e <=> è 64 bit). In tal caso, la sostituzione di <=> in questa espressione con un tipo intero di dimensioni di puntatore come <=> o <=> (su Windows) dovrebbe funzionare, poiché sono consentite le conversioni tra <=> e numeri interi di dimensioni di puntatore, quindi sono conversioni tra numeri interi puntatori e puntatori.

Le versioni successive di GCC hanno la seguente soppressione degli avvisi opzioni , ma non per C ++ :

  

-Wno-int-to-pointer-cast (solo C e Objective-C)
  Elimina gli avvisi dai cast al tipo di puntatore di un numero intero di dimensioni diverse.

     

-Wno-pointer-to-int-cast (solo C e Objective-C)
  Elimina gli avvisi dai cast da un puntatore a un tipo intero di dimensioni diverse.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top