J'ai le code C suivant: lorsque je le compile (avec Microsoft J'ai vérifié MS Docs sur l'opérateur conditionnel et ils indiquent que si les deux opérandes sont de même type, le résultat sera du même type. Il devrait donc fonctionner comme première comparaison. Est-ce que je manque quelque chose? P> cl code>, de MS SDK 7,
-w3 code > Niveau d'avertissement), la deuxième comparaison émet un avertissement: C4018, instabilité signée / non signée. La première comparaison émet aucun avertissement. P>
gcc -wall -wextra -pedantique code> et n'a aucun avertissement. P> p >
3 Réponses :
Ceci est probablement dû aux règles de conversion arithmétiques: tout d'abord, tout type de type de conversion entier inférieur à Si le résultat sera Deuxièmement, comme les deux opérandes se retrouvent avec le même rang de conversion, mais un non signé, l'autre opérande sera également converti en un type non signé. P> sémantiquement, vos expressions lues p> et p> Le compilateur est apparemment assez intelligent pour noter que le premier cas ne peut pas causer de problèmes, mais échoue à le second. p> Le commentaire de Steve Jessop explique bien comment cela pourrait arriver: P> J'imagine que dans le premier cas, le compilateur pense: "J'ai un opérateur de comparaison dont les types d'opérande sont Dans le second cas, il pense: "J'ai un opérateur de comparaison dont les types d'opérande sont int code> (par exemple,
non signé char code>) favorisera à
int code> ou
non signé INT code>.
int code> ou
non signé INT code> ne dépend pas de la signature du type d'origine, mais sa plage:
int code> est utilisé même pour des types non signés tant que toutes les valeurs peuvent être représentées, ce qui est le cas pour
sans signé Char code> sur les architectures traditionnelles. p>
non signé INT code> et
non signé Char code>. Pas besoin d'un avertissement , appliquons maintenant une promotion suivie d'une conversion habituelle ». P>
non signé int code> et
int code> (que j'ai dérivé le type de l'expression conditionnelle sur le RHS). Meilleur avertissant de cela! ". P>
blockQuote> p>
Strictement parlant, le 2e cas est équivalent à A <(INT) (INT) (int) (B? (Int) B: (int) b: (int) c) code> en raison d'une règle étrange spéciale dans l'opérateur conditionnel. 6.5.15 / 3
Si les deuxième et troisième opérandes ont des types arithmétiques, le type de résultat qui serait déterminé par les conversions arithmétiques habituelles, ont-ils été appliqués à ces deux opérandes, est le type de résultat. Code > Bien sûr, cela n'a pas d'importance pour le résultat dans ce cas particulier.
@LUNDIN: En fait, j'ai réfléchi à ce que cette conversion (ainsi que la promotion du premier B code>) mais a décidé de cela pour des raisons pédagogiques; Votre réponse est en effet plus complète, donc +1 de moi
J'imagine que dans le premier cas, le compilateur pense: "J'ai un opérande de comparaison dont les types sont non signé int code> et
non signé char code>. Pas besoin d'un avertissement, maintenant appliquons maintenant Promotion suivie d'une conversion habituelle ». Dans le second cas, il pense: "J'ai un opérande de comparaison dont les types sont
non signés INT code> et
int code> (que j'ai dérivé le type de l'expression conditionnelle sur le RHS). Meilleur avertir à ce sujet! ".
@Stevejessop: J'espère que ça ne vous dérange pas de me voler votre belle explication
@Stevejessop En fait, cela pourrait être, car le compilateur n'est pas obligé de faire toutes les promotions implicites si elle peut dire qu'elles n'affecteront pas le résultat de l'expression. Supposons que cela traduit ce code directement dans "Afficher A et B dans des registres CPU 32 bits, puis comparez".
@Christoph: Ne vous dérange pas du tout, bien que j'ai typée "Opérande" au lieu de "opérateur" deux fois! Dis peut-être "un opérateur de comparaison dont les types d'opérande sont ..."
Chaque fois qu'un type de caractère est utilisé dans une expression, les règles de promotion entier en C convertit implicitement à un Chaque fois que deux entiers du même rang mais que la signature différente est utilisée dans une expression, la signature est implicitement convertie en non signé. Ceci est déterminé par les conversions arithmétiques habituelles em>, aka équilibre em>. P>
Donc, votre première expression est convertie en p>
Avant que tout ce qui soit fait. P>
dans la deuxième expression que nous avons Les promotions entier sont effectuées sur tous les caractères, il est donc implicitement converti en p>
Ensuite, une règle étrange et obscurée de l'opérateur conditionnel dicte que le 2e et 3ème opérateur de l'opérateur?: L'opérateur doit être équilibré avec les conversions arithmétiques habituelles. Dans ce cas, ils sont déjà du même type, alors rien ne se passe. Nous finissons avec p>
L'équilibrage se produit à nouveau, le résultat sera évalué comme p>
Quand je le compile avec Microsoft P>
blockQuote>
Lorsque vous compilez avec Microsoft, tous les paris sont éteints, leur compilateur est très pauvre pour suivre la norme. Attendez-vous à des avertissements bizarres et illogiques. P> si (a est égal au pseudo
si (non signé int
int code>. Après cela est fait, vous avez P>
si (non signé int
si (non signé INT
si (a <(b: b: c)) code> qui équivaut à Pseudo p>
si (non signé INT <(non signé Char? non signé Char: Unsigné Char)) Code>. P>
si (non signé INT <(int? int: int)) code>. p>
si (non signé int
si (non signé INT
Les règles sont différentes entre C et C ++. La norme appropriée peut être difficile à juger lors de la compilation C avec MSVC, mais heureusement dans ce cas, C89 et C99 sont les mêmes. P>
en C89 3.3.15: P>
Si les deuxième et troisième opérandes ont un type arithmétique, l'habitude Les conversions arithmétiques sont effectuées pour les amener à un type commun et le résultat a ce type p> blockQuote>
en C99 6.5.15 / 5: P>
Si les deuxième et troisième opérandes ont un type arithmétique, le résultat type qui serait déterminé par les conversions arithmétiques habituelles, ont-ils été appliqués à ces deux opérandes, est le type de résultat. P> blockQuote>
en C ++ 03 5.16 / 4: P>
Si les deuxième et troisième opérandes sont des lvalues et ont le même type, Le résultat est de ce type et est un lvalue p> blockQuote>
Ainsi, lorsque vous, disons: "Si les deux opérandes sont de même type, le résultat sera du même type, il devrait donc fonctionner comme la première comparaison", qui ne s'applique qu'à C ++, non à C. en C Type du RHS de cette comparaison est
INT code>. En C ++, le RHS serait une lvalue de type
non signé Char code> comme prévu. P>
Les promotions entières ne s'appliqueraient-elles pas même en C ++ après la conversion de Lvalue-to-RValue?
@Cristoph: Oui. En C ++, les types d'opérandes de << / code> seraient
non signé INT code> et
non signé Char code>. alors i> Promotion et conversion s'appliquent aux opérandes. En C, les types des opérandes de
<< / code> sont
non signé int code> et
int code>, puis la promotion et la conversion s'appliquent aux opérandes.
Ma "réponse" devrait probablement être un commentaire, en fait. Il parle "si les deux opérandes sont de même type, le résultat sera du même type ... je manque quelque chose?" (tiré de la DOCS de MS), plutôt que la question actuelle impliquée "Pourquoi est-ce que je reçois cet avertissement?". Mais il n'ya aucun moyen de répondre à ces citations standard dans un commentaire et, étant donné que la seule question que vous demandez est ", manque-t-il quelque chose?" alors la réponse à votre question est "oui" ;-)
@Stevejessop vous êtes absolument juste; Si je le compile en mode C ++ (avec -TP code>) je n'arrête pas d'avertissement ici. Merci!
Tous les avertissements de compilation sont-ils allumés dans vos options de compilateur?
Oui, un bug / une fonctionnalité non confirmée. Je suis allé dessus et je me suis lancé, si VC se plaint et ne le pense pas plus.
@CowBoydan Oui,
-W3 code>. Si je spécifie un niveau d'avertissement, il n'y a aucun avertissement.
GCC ne produit aucun avertissement.