Question

J'essaie de créer cairomm pour gtkmm sous Windows en utilisant mingw. La compilation est interrompue lors d’un appel de fonction dont le paramètre effectue une réinterprétation-diffusion d’une valeur booléenne vers un vide *.

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

C’est là que le code se rompt et que la raison est & "; invalide réinterpréter_cast de bool en void * &"; Pourquoi cela se produit-il et comment puis-je modifier cette ligne pour la compiler? Besoin d'aide

Était-ce utile?

La solution

Je vois que ce sont des données utilisateur et que vous avez le contrôle sur ce qui est fait avec la valeur, transformez le bool en un int: reinterpret_cast<void *> (static_cast<int> (true)). Cela est logique dans la mesure où le paramètre void * remplace les fonctions de modèle dans cette bibliothèque ANSI-C. Tout ce dont vous avez besoin est une valeur true / false. Donc, il ne devrait y avoir aucun danger à coder temporairement ceci en tant que pointeur tant qu'il est bien documenté en tant que tel. Vraiment, vous seriez mieux avec ceci: reinterpret_cast<void *> (1) ou reinterpret_cast<void *> (+true).

Autres conseils

Il semble que cela devrait fonctionner, conformément à la norme. La section 3.9.1-7 indique que bool est un type intégral, et 5.2.10-5 indique qu'une valeur de type intégral peut être explicitement convertie en pointeur à l'aide de reinterpret_cast. Il semble que votre compilateur n’est pas totalement standard.

Pourriez-vous vous en tirer en modifiant le & "vrai &"; à un 1? La conversion entre les entiers et les types de pointeurs est une tradition ancienne et déshonorante en C et donc en C ++, et il serait surprenant de trouver un compilateur qui ne le ferait pas.

Ou, si vous devez vraiment faire cela, essayez (void *) true. Ensuite, lavez-vous les mains.

reinterpret_cast est une mauvaise idée . Dites-nous en plus sur le problème que vous essayez de résoudre, et peut-être trouverons-nous une solution sans recourir à la réinterprétation. Pourquoi voulez-vous convertir bool en void *?

Le seul compilateur que j'ai à me plaindre à ce sujet est GCC (MinGW avec GCC 3.4.5) - et je ne sais pas pourquoi. La norme semble indiquer clairement que cela est autorisé:

  

3.9.1 Types fondamentaux

     

...

     

Types bool, char, wchar_t et le   les types entiers signés et non signés sont   collectivement appelés types intégraux.

     

5.2.10 Réinterpréter le casting:

     

...

     

Une valeur de type intégral ou   type d'énumération peut être explicitement   converti en un pointeur.

Cela étant dit, solution de contournement de monjardin d'utilisation reinterpret_cast<void *> (static_cast<int> (true)) ou reinterpret_cast<void *> (1) sont des solutions de contournement raisonnables.

Cela échoue car la distribution n’a aucun sens - vous prenez une valeur booléenne vrai / faux et demandez à la compilation de l’interpréter comme un pointeur, ce qui en un mot est un emplacement de mémoire. Les deux ne sont même pas liés.

Essayez une version plus récente de votre compilateur. Je viens de tester et cette distribution fonctionne au moins sur gcc 4.1 et supérieur. Je ne sais pas exactement comment les versions de gcc correspondent aux versions de mingw.

Dans certaines situations, il est hautement souhaitable que le compilateur prévienne ou commette une erreur sur un code tel que reinterpret_cast<void*>(true), même si ce code est apparemment légal en C ++. Par exemple, il facilite le portage sur des plates-formes 64 bits.

Transformer un pointeur 64 bits en un type intégral plus petit qu'un pointeur (tel que int ou bool) constitue souvent un bogue: vous tronquez la valeur du pointeur. De plus, la spécification C ++ ne semble pas garantir que vous pouvez directement transformer un pointeur en un type intégral plus petit (c'est nous qui soulignons):

  

5.2.10.4. Un pointeur peut être explicitement converti en tout type intégral suffisamment grand pour le contenir . La fonction de mappage est définie par l'implémentation.

De même, la conversion d'un type entier plus petit dans un pointeur 64 bits (comme avec reinterpret_cast<void*>(static_cast<int>(true))) est également souvent un bogue: le compilateur doit renseigner les bits supérieurs du pointeur avec quelque chose; est-il rempli de zéros ou prolongé de signe? Sauf si vous écrivez du code de bas niveau spécifique à une plate-forme pour un accès d'E / S mappé en mémoire ou un DMA, vous ne voulez généralement pas le faire du tout, à moins que vous ne fassiez quelque chose de malicieux (comme insérer un booléen dans un pointeur ). Mais la spécification C ++ ne semble pas avoir grand chose à dire sur ce cas, sauf qu'il est défini par la mise en oeuvre (note de bas de page omise):

  

5.2.10.5. Une valeur de type intégral ou de type énumération peut être explicitement convertie en un pointeur. *

     

Un pointeur converti en un entier de taille suffisante (s'il en existe une dans l'implémentation) et revenant au même type de pointeur aura sa valeur d'origine; Les mappages entre les pointeurs et les entiers sont par ailleurs définis par l'implémentation.

@monjardin a suggéré void*. Si l'origine de l'erreur est le décalage entre la taille du type entier et la taille du pointeur, cela fonctionnera sur la plupart des plates-formes 32 bits (où uintptr_t et DWORD_PTR sont tous deux 32 bits), mais échouent pour la plupart des systèmes 64 bits. plates-formes (où <=> correspond à 32 bits et <=> à 64 bits). Dans ce cas, le remplacement de <=> dans cette expression par un type entier de la taille d'un pointeur, tel que <=> ou <=> (sous Windows), devrait fonctionner, car les conversions entre les entiers de <=> et de la taille d'un pointeur sont autorisées. sont des conversions entre des entiers et des pointeurs de la taille d'un pointeur.

Les suppression des avertissements dans les versions ultérieures de GCC sont les suivants: options , mais pas pour C ++ :

  

-Wno-int-to-pointer-cast (uniquement pour C et Objective-C)
  Supprimez les avertissements des conversions en types de pointeur d'un entier de taille différente.

     

-Wno-pointeur-sur-diffusion (C et Objective-C uniquement)
  Supprimer les avertissements des conversions d'un pointeur sur un type entier de taille différente.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top