2017-09-18 4 views
1

J'ai le code suivant:Conversion de temps à courte erreur

int main() 
{ 
    short s(0); 
    long l(10); 

    s += static_cast<short>(l); 
} 

Je compile cela avec g ++ et je reçois l'erreur suivante:

..\src\main.cpp:6:7: warning: conversion to 'short int' from 'int' may alter its value [-Wconversion] 

je n'ai absolument aucune idée pourquoi cette se passe, car je pensais que "static_cast" permettait d'éviter ce roi des avertissements.

Merci pour toute aide fournie.

+0

Quel compilateur et quelle version utilisez-vous? [Je ne peux pas reproduire] (http://coliru.stacked-crooked.com/a/92d6d2ae09aadced) – NathanOliver

+2

@NathanOliver ajoute '-Wconversion' et déclenche l'avertissement. – Quentin

+1

Change 's + = static_cast (l);' '' '' s = s + s; 'et vous obtenez toujours l'avertissement. Suggère moi l'élargissement automatique de l'opérateur 'built +' Update: Fount it _ "... les opérateurs arithmétiques n'acceptent pas les types plus petits que int comme arguments, ..." _ source: http://en.cppreference.com/w/ cpp/language/implicit_conversion –

Répondre

2

promotion intégrale de short est nécessaire, si l'élargissement est inévitable, si vous effectuez une static_cast vous jetterai le résultat à un short

En bref:

  • vous effectuez un short = short + short
    • (la static_cast du long fait la deuxième v aLuì un short)
  • promotion intégrale se produit avant que les opérandes sont vérifiées pour le type
    • de sorte que vous obtiendrez short = int + int
  • conversion implicite du int résultant de short crée un avertissement

De [Expr]:

Many binary operators that expect operands of arithmetic or enumeration type cause conversions and yield result types in a similar way. The purpose is to yield a common type, which is also the type of the result. This pattern is called the usual arithmetic conversions, which are defined as follows:
...
Otherwise, the integral promotions (7.6) shall be performed on both operands. Then the following rules shall be applied to the promoted operands
- If both operands have the same type, no further conversion is needed.

De [conv.prom]

A prvalue of an integer type other than bool , char16_t , char32_t , or wchar_t whose integer conversion rank (7.15) is less than the rank of int can be converted to a prvalue of type int if int can represent all the values of the source type; otherwise, the source prvalue can be converted to a prvalue of type unsigned int .

Et en effet short a un rang inférieur à celui int:

De [conv.rank]

The rank of a signed integer type shall be greater than the rank of any signed integer type with a smaller size.

Pour effectuer la distribution (pour faire disparaître l'avertissement), voir les commentaires de Richard Crittenden sur le PO ou Nathan Oliver's answer

2

Même si vous affectez l à un short, une autre conversion est en train de se produire. Lorsque vous faites

s += static_cast<short>(l); 

[expr.ass]/7 dit qu'il est le même que

s = s + static_cast<short>(l) 

Et cette transformation est ce qui vous donne la int dans l'avertissement que vous recevez.

La raison en est que les opérateurs intégrés n'existent pas pour les types inférieurs à int. Comme les deux types sont short, ils sont convertis en int ce qui vous donne un int pour le résultat et vous essayez maintenant d'affecter ce int à un short qui pourrait déborder. Pour contourner ce problème, vous pouvez utiliser

s = static_cast<short>(s + l); 

qui convertit le résultat à un short et fait ensuite l'affectation.