12
votes

Questions concernant "AVERTISSEMENT C4312:" Type Cast ""

Ceci est le code que j'ai:

warning C4312: 'type cast' : conversion from 'UINT' to 'HMENU' of greater size


0 commentaires

3 Réponses :


2
votes

Vous coulez un uint 32bit à un pointeur 64 bits. C'est suicide - vous essayez de pointer quelque chose mais oublié la moitié de son emplacement! Vous devez absolument prendre un uint_ptr. Lorsque vous lancez un pointeur sur un int, le comportement est OK si l'INT a la même taille que le pointeur. D'autre, c'est la fin de votre demande d'exécution d'une violation d'accès.

EDIT:
Pourquoi le compilateur pense-t-il que c'est une mauvaise idée de se lancer à un type plus grand?
RÉ. au-dessus

Quel est le meilleur moyen de se débarrasser de l'avertissement? (Je ne veux pas le désactiver.)
Résoudre le problème. Ce code va presque certainement installer.

Faire une double type de type comme ceci: (hmenu) (uint_ptr) ID se débarrasse de l'avertissement. Pourquoi / comment?
Il arrive parce que la coulée d'un uint uint_ptr est parfaitement valide- uint_ptr est juste un type intégral, il n'y a pas de perte de données.

Désactiver "Détecter les problèmes de portabilité 64 bits" (WP64) se débarrasse également de l'avertissement. Pourquoi WP64 est-il obsolète? Devrais-je l'avoir sur?
C'est obsolète parce que, en fait, je ne me souviens pas trop pourquoi. Je pense que cela avertit un peu trop facilement. Mais pour la base "Ne pas lancer des types d'intégrale et des pointeurs", vous devez certainement le laisser.


6 commentaires

Je ne comprends pas. Pouvez-vous s'il vous plaît développer cette réponse? Je ne traite pas de pointeurs ici. C'est juste un identifiant de contrôle.


Hmenu est une poignée à un menu, qui est un pointeur. Typedef Hmenu__ * hmenu est la définition de HMENU.


Le code fonctionne bien comme c'est le cas. Pas de crash. Copier / coller de MSDN: "Pour une fenêtre enfant, HMENU Spécifie l'identifiant de la fenêtre enfant, une valeur entière utilisée par une commande de boîte de dialogue pour en informer son parent des événements."


Il dit également clairement "une poignée à un menu". Le fait que votre code ne fonctionne que ne montre que vous l'utilisez comme une seule partie de ses fonctionnalités. Si je devais faire un menu et le transmettre, votre code s'écrasera. Vous mendez des bugs. Prenez un uint_ptr, c'est quatre caractères ajouté. Visual Studio a raison d'avertir.


Ouais, ça sonne comme la meilleure solution. Merci de me revenir avec des réponses à mes commentaires.


@Deadmg: pas vrai. Le code ne s'écrasera pas, car le casting dans le code est parfaitement sûr et correct du point de vue Winapi. Lorsque vous créez une fenêtre de style ws_child , vous devez transmettre l'ID de l'enfant WINODOW CAST sur HMENU Type. C'est à quoi ça marche dans Winapi. Ce n'est pas "une poignée à un menu". Ce serait "une poignée à un menu" si les fenêtres n'étaient pas un ws_child .



19
votes

Le type qui se cache derrière le nom HMENU est en réalité un type pointeur . Le compilateur vous dit que la casage d'un type entier plus petit à un type de pointeur plus important n'a aucun sens, car la valeur du pointeur résultant sera "incomplète", c'est-à-dire les bits d'ordre supérieur Si la valeur du pointeur sera remplie de zéros. Ce dernier a très peu de sens avec les types de pointeur.

Dans votre cas particulier, c'est sûr, car ce HMENU n'est pas vraiment censé être un pointeur qui pointe n'importe où. Cependant, le compilateur ne sait pas que, c'est pourquoi cela émet un avertissement. Utilisez un type plus grand comme type intermédiaire dans la distribution et l'avertissement s'éloignera (vous avez suggéré que vous-même), car dans ce cas, vous faites deux cases: plus petit entier à un entier plus grand, et puis plus grand entier à un pointeur. Un entier plus petit à un entier plus grand est un casting arithmétique , pour lequel il est parfaitement logique de remplir les bits d'ordre supérieur avec des zéros (la valeur représentée ne change pas), donc il n'y aura pas d'avertissement .


1 commentaires

Merci pour la grande explication sur la raison pour laquelle la double distribution fonctionne!



2
votes

Pourquoi le compilateur pense-t-il que c'est une mauvaise idée de se lancer à un type plus grand?

La coulée entre types de taille différente est généralement une opération problématique, car le type source pourrait ne pas être en mesure de représenter toutes les valeurs nécessaires à la cible.

Quel est le meilleur moyen de se débarrasser de l'avertissement? (Je ne veux pas le désactiver.)

Je dirais, utilisez hmenu partout et déclarez votre fonction comme xxx

Faire une double type de type comme ceci: (hmenu) (uint_ptr) ID se débarrasse de l'avertissement. Pourquoi / comment?

uint_ptr est un type d'entier suffisamment grand pour contenir toutes les valeurs de pointeur, donc les avertissements disparaissent.

HMENU est un Type de pointeur. Cela ne signifie pas qu'une valeur d'un hmenu est en réalité un pointeur, mais c'est un piratage qui vous désactive implicitement, par exemple. hmenu et hwnd (car hmenu et hwnd est quelque chose comme struct _hmenu * et struct _hwnd * , respectivement, qui ne sont pas compatibles, tandis que uint s) serait).


0 commentaires