7
votes

réinterpret_cast à vide * ne fonctionne pas avec les pointeurs de la fonction

Je veux réinterpréter jeter un pointeur de fonction dans une variable Void *. Le type du pointeur de fonction sera de type classe * (*) (vide *) .

ci-dessous est le code d'échantillon, xxx

Le code ci-dessus fonctionne bien avec les compilateurs Visual Studio / X86. Mais avec le compilateur de bras, il donne une erreur de compilation. Je ne sais pas pourquoi.

erreur: # 694: Reterpret_cast ne peut pas jeter const ou autre type qualificatifs

J'ai lu l'explication dans casting d'un pointeur de fonction à un autre Tapez

J'étais préoccupé par l'explication ci-dessous.

Casting entre les pointeurs de la fonction et Pointeurs réguliers (par exemple, casting d'un void (*) (void) à un vide * ). Une fonction Les pointeurs ne sont pas nécessairement les mêmes taille comme des pointeurs réguliers, depuis sur certaines architectures qu'ils pourraient contenir informations contextuelles supplémentaires. Cette va probablement fonctionner ok sur x86, mais rappelez-vous que c'est un comportement indéfini.

Comment faire de telles conversions de Void (*) (vide *) -> Void * efficacement de sorte qu'il compile presque la même chose dans la plupart des compilateurs?


2 commentaires

Vous devriez au moins mettre dans une affirmation selon laquelle tailleOf (vide *)> = Tailleof (test ** (*) (NOID **)) . Si cela affirme échoue, il n'existe évidemment aucun moyen de stocker le pointeur de la fonction dans un vide * . Si l'affirmation n'a pas échoué, cela ne garantit toujours rien, mais au moins il est possible que la distribution puisse fonctionner.


Notez que P a en fait un test de type ** (void **), et est une fonction, pas un pointeur de fonction. Mettre un espace dans " test * * " n'affecte pas l'analyse.


5 Réponses :


8
votes

reterpret_cast code> ne peut pas être utilisé pour lancer un pointeur pour fonctionner à un vide * code>. Bien qu'il y ait quelques autres choses supplémentaires qu'un CAST C peut faire ce qui n'est pas autorisé par une combinaison d'une combinaison de jeux statiques, de réinterpret et de const, cette conversion n'est pas l'une d'entre elles.

en C, la distribution est autorisée, mais c'est un comportement Isn 't défini (c.-à-d. Un aller-retour n'est pas garanti de travailler). p>

Certaines fonctions POSIX ont besoin de la conversion pour être bien utiles. P>

J'ai joué avec plusieurs compilateurs que j'ai ici: p>

  • Aucun n'empêche la coutée C, même dans le mode de conformité le plus élevé. Certains donnent un avertissement en fonction du niveau d'avertissement et de conformité, d'autres n'ont donné aucun avertissement tout ce que j'ai essayé. li>
  • Le réinterpret_cast était une erreur avec certains compilateurs, même dans le niveau le plus détendu, tandis que les autres l'acceptaient dans tous les cas sans jamais faire un avertissement. Li> ul>

    dans le dernier brouillage disponible pour C ++ 0x, le REINIERPRET_CAST CODE> entre les pointeurs de fonction et les pointeurs d'objets est pris en charge sous condition. P>

    Notez que si cela a du sens. ou ne dépendra pas de la cible plus que le compilateur: un compilateur portable comme GCC aura un comportement imposé par l'architecture cible et éventuellement abi. p>

    comme d'autres ont fait la remarque, P>

    Test* *p(void **a);
    


1 commentaires

(Près de -1) Je ne pense pas que cela a raison, pouvez-vous fournir une référence pour cela? Je crois comprendre que C-style Cast est défini en termes de nouveaux styles de distribution. Par conséquent, s'il n'est pas possible de le faire à l'aide de Reterpret_cast, il n'est pas possible avec une mise en forme de style C.



0
votes

ne devrait pas test * * p (vide ** a); être test * (* p) (vide ** a) ?

Peut-être que c'est votre problème?


1 commentaires

Test * p (void a) est également résolu à taper le test * () (void ) .. Donc, je pense que les deux représentations sont valides. Je suis sûr de cela parce que j'ai essayé de cette façon aussi ..



4
votes

Si vous cherchez simplement à stocker différents types de pointeur de fonction dans une liste, vous pouvez vous lancer sur un type de pointeur de fonction commun: xxx

ceci est valide pour faire via Reterpret_cast (5.2.10 / 6):

Un pointeur sur une fonction peut être explicitement converti en un pointeur à une fonction d'un type différent. L'effet d'appeler une fonction via un pointeur à un type de fonction (8.3.5) qui n'est pas identique au type utilisé dans la définition de la fonction est indéfinie. Sauf que de convertir une rvalue de type "pointeur en T1" au type "pointeur en T2" (où T1 et T2 sont des types de fonction) et que le type d'origine donne la valeur de pointeur d'origine, le résultat d'une telle conversion de pointeur est indéterminée .


0 commentaires

7
votes

réinterpret_cast ne peut être utilisé que pour

  • Ajouter Constenness
  • Convertissez un pointeur en un type d'intégration suffisamment grand pour le maintenir et le dos
  • Convertissez un pointeur en une fonction à un pointeur sur une fonction de type différent
  • Convertissez un pointeur en un objet à un pointeur à un objet de type différent
  • Convertissez un pointeur en une fonction de membre à un pointeur à une fonction de membre de type différent
  • Convertissez un pointeur en un objet membre à un pointeur à un objet membre de type différent
  • et reterpret_cast (x) est équivalent à * reterpret_cast (& x) (à l'aide de et et et < Code> * ) Chaque fois que la deuxième coulée est possible en utilisant les règles ci-dessus.

    (voir la section 5.2.10 de la norme)

    Cela signifie notamment qu'un déclencheur d'un pointeur pour fonctionner à Void * n'est pas possible, mais vous pouvez le jeter à void (*) () . < / p>


    edit (2017): La réponse ci-dessus n'est correcte que pour C ++ 03. En C ++ 11 à C ++ 17, il s'agit de la mise en œuvre de la mise en œuvre si les conversions entre les pointeurs de fonction et void * sont autorisés. Ceci est généralement le cas sur les systèmes compatibles POSIX car dlsym () est déclaré pour renvoyer Void * et les clients sont attendus à REINIERPRET_CAST Type de pointeur de fonction correct.

    voir CPPreference.com pour la liste complète des conversions autorisées. < / p>


0 commentaires

3
votes

D'autres ont souligné que vous ne pouvez pas faire ce casting (fortement parlant, casting à Void * code> tout que vous utilisez Reterpret_cast CODE> n'est pas autorisé - mais silencieusement toléré par les compilateurs. static_cast code> est destiné à être utilisé ici).

Je fais habituellement ce qui suit, ce qui fait un type de jeu de mots, et est la façon recommandée de le faire, selon le manuel de dlopen code> (qui consiste à faire la casting converse - Casting de em> void * code> to em> un pointeur de fonction). Prendre l'adresse du pointeur de fonction vous donnera un pointeur de données: pointeur sur un pointeur de fonction. Cela vous permettra de le jeter à Void * code>. Il prétend qu'il préconise un vide * code> (au lieu d'un pointeur de fonction), puis la lit. p> xxx pré>

la distribution intermédiaire à vide * code> équivaut à utiliser deux static_cast code> s en interne et que GCC soit silencieux sur l'avertissement d'un type de jeu de mots. Utilisation de C ++ Style CastS, cela ressemble à une combinaison de deux static_cast code> 's p> xxx pré>

J'ai constaté que l'utilisation de cette technique, GCC remarque automatiquement quand la gauche et les bons types diffèrent de taille et crachent un avertissement dans ce cas. Inutile de dire que comme avec toutes les techniques qui tentent de contourner cette limitation, ceci est un comportement indéfini. p>


Si vous avez une fonction, et que vous voulez un void * code> en pointant dessus, vous pouvez le faire tout en une seule ligne, mais c'est un peu lourd sur la syntaxe. Voici comment cela peut être fait, mais je ne le recommande pas si vous avez des problèmes pour le lire - vous pouvez toutefois l'utiliser à l'intérieur d'une macro p> xxx pré>

le truc sur Commencez à être capable de faire le type mais consiste à transformer le pointeur de fonction temporaire sur une référence de LValue à la const, que vous pouvez prendre l'adresse, puis procéder comme ci-dessus. P>

Utilisation de style C ++ explicite Static_cast CODE> CASTS, Ceci semble beaucoup plus compliqué, car vous devez en tenir compte de la constitution. Le style C a choisi automatiquement de cela. Amusez-vous! P>

int main() {
    Test** pF(void **a);
    void *p = *static_cast<void* const*>(
      static_cast<void const*>(
        &static_cast<Test** (* const&)(void **a)>(&pF)));
}


1 commentaires

Merci pour cela - le code fait crawler mes globes oculaires, mais il semble fonctionner correctement et éviter les avertissements / erreurs même avec des niveaux d'avertissement maximum sur GCC et Scrang.