97 votes

Avertissement C ++: division du double par zéro

Cas 1:

#include <iostream>

int main()
{
    double d = 15.50;
    std::cout<<(d/0.0)<<std::endl;
}

Il se compile sans mises en garde et imprime inf. OK, C++ peut gérer la division par zéro, (voir en direct).

Mais,

Cas 2:

#include <iostream>

int main()
{
    double d = 15.50;
    std::cout<<(d/0)<<std::endl;
}

Le compilateur donne l'avertissement suivant (voir en direct):

warning: division by zero [-Wdiv-by-zero]
     std::cout<<(d/0)<<std::endl;

Pourquoi le compilateur de donner un avertissement dans le second cas?

Est - 0 != 0.0?

Edit:

#include <iostream>

int main()
{
    if(0 == 0.0)
        std::cout<<"Same"<<std::endl;
    else
        std::cout<<"Not same"<<std::endl;
}

sortie:

Same

108voto

Motti Points 32921

Floating point de la division par zéro est bien défini par l'IEEE et donne l'infini (qu'elle soit positive ou négative en fonction de la valeur du numérateur (ou NaN de ±0) ).

Pour les entiers, il n'y a aucun moyen de représenter l'infini et de la langue définit l'opération à avoir un comportement indéterminé de sorte que le compilateur utilement essaie de vous orienter clairement de ce chemin.

Toutefois, dans ce cas, puisque le numérateur est un double, le diviseur (0) devrait être promu à un double aussi, et il n'y a pas de raison de donner un avertissement ici tout en lui donnant un avertissement pour 0.0 donc je pense que c'est un bug du compilateur.

42voto

Matt McNabb Points 14273

En C++ Standard, deux cas sont à un comportement indéterminé. Tout peut arriver, y compris le formatage de votre disque dur. Vous ne devriez pas attendre, ou appuyer sur "retour inf. Ok" ou tout autre comportement.

Le compilateur apparemment décide de donner un avertissement dans un cas et pas dans l'autre, mais cela ne signifie pas qu'un code est OK et on ne l'est pas. C'est juste un caprice de le compilateur de la génération de mises en garde.

À partir du C++17 standard [expr.mul]/4:

Le binaire / opérateur donne le quotient et le binaire % opérateur donne le reste de la division de la première expression par le second. Si le second opérande de / ou % est zéro, le comportement est indéfini.

13voto

Yksisarvinen Points 4653

Ma meilleure supposition de répondre à cette question serait que le compilateur émet un avertissement avant d'effectuer la conversion d' int de double.

Ainsi, les étapes serait comme ceci:

  1. Analyser l'expression
  2. Opérateur arithmétique /(T, T2)T=double, T2=int.
  3. Vérifiez que std::is_integral<T2>::value est true et b == 0 - ce qui déclenche l'alerte.
  4. Émettre d'avertissement
  5. Effectuer la conversion implicite d' T2 de double
  6. Effectuer bien défini division (depuis compilateur a décidé d'utiliser la norme IEEE 754).

C'est bien sûr la spéculation et est basé sur le compilateur définies. De point de vue, nous avons affaire à de possibles Comportements Indéfinis.


Veuillez noter que ce comportement est normal selon la documentation de GCC
(btw. il semble que cet indicateur ne peut pas être utilisé explicitement dans le CCAG 8.1)

-Wdiv par zéro
De les avertir au moment de la compilation division entière par zéro. C'est par défaut. Pour inhiber les messages d'avertissement, utilisez -Wno-div-by-zero. Virgule flottante la division par zéro n'est pas averti, car il peut être un moyen légitime de l'obtention d'infinis et NaNs.

9voto

bolov Points 4005

Je n'entrerai pas dans le UB / pas UB débâcle de cette réponse.

Je veux juste souligner que l' 0 et 0.0 sont différentes malgré 0 == 0.0 de l'évaluation à la valeur true. 0 est int - littérale, 0.0 est double littérale.

Toutefois, dans ce cas, le résultat final est le même: d/0 est floating point de la division, car d est double et donc, 0 est implicitement converti en double.

7voto

Cássio Renan Points 1605

Je dirais que, foo/0 et foo/0.0 sont pas les mêmes. À savoir, l'effet résultant de la première (division d'entier ou à virgule flottante de la division) est très dépendant du type d' foo, tandis que le même n'est pas vrai pour la deuxième fois (il a toujours une division à virgule flottante).

Si l'un des deux est UB n'est pas pertinent. Citant le standard:

Admissible comportement indéfini plages d'ignorer la situation complètement avec des résultats imprévisibles, à se comporter lors de la traduction ou de l'exécution du programme dans documenté de façon caractéristique de l'environnement (avec ou sans émission d'un message de diagnostic), à la terminaison d'une traduction ou d'exécution (avec l'émission d'un message de diagnostic).

(L'emphase est mienne)

Considérer la "suggérer des parenthèses autour de cession utilisé comme valeur de vérité" avertissement: Le moyen de dire au compilateur que vous vraiment voulez utiliser le résultat de la cession est en étant explicite, et l'ajout de parenthèses autour de la cession. La déclaration a le même effet, mais il indique au compilateur que vous savez ce que vous faites. La même chose peut être dit à propos de foo/0.0: Puisque vous êtes explicitement dire au compilateur "C'est à virgule flottante de la division" à l'aide d' 0.0 au lieu de 0, le compilateur confiance en vous et n'émettra un avertissement.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X