#include <fenv.h> // <cfenv> en C++
Une exception en virgule flottante n'est pas forcément une exception au sens C++ ou Java. Dans le modèle de
<fenv.h>, il s'agit d'un indicateur d'état qui peut être levé par un calcul : division par zéro,
dépassement de capacité, résultat inexact, opération invalide...
Avant d'observer ces indicateurs, il est recommandé d'activer le pragma FENV_ACCESS.
Sans lui, le compilateur peut réaliser des optimisations incompatibles avec l'observation fine de l'environnement flottant.
Le type fexcept_t représente une sauvegarde des indicateurs d'exception. Il ne faut pas supposer qu'il s'agit
d'un entier : son contenu est dépendant de l'implémentation et doit être produit par fegetexceptflag.
| Macro | Description |
|---|---|
FE_ALL_EXCEPT |
Masque correspondant à toutes les exceptions supportées par l'implémentation. |
FE_DIVBYZERO |
Division par zéro en virgule flottante. |
FE_INEXACT |
Résultat inexact, par exemple après un arrondi nécessaire. |
FE_INVALID |
Opération invalide, par exemple certaines opérations sur NaN ou racines carrées impossibles. |
FE_OVERFLOW |
Dépassement de capacité par le haut. |
FE_SNANS_ALWAYS_SIGNAL (C23) |
Macro optionnelle liée aux NaN signalants, fournie uniquement par certaines implémentations IEC 60559. |
FE_UNDERFLOW |
Dépassement de capacité par le bas. |
| Fonction | Rôle | Depuis |
|---|---|---|
int feclearexcept( int excepts ); |
Efface les indicateurs d'exception indiqués. | C99 |
int fegetexceptflag( fexcept_t * flagp, int excepts ); |
Sauvegarde une représentation des indicateurs demandés. | C99 |
int feraiseexcept( int excepts ); |
Lève explicitement les exceptions indiquées. | C99 |
int fesetexcept( int excepts ); |
Positionne des indicateurs d'exception sans déclencher les effets associés à une vraie levée. | C23 |
int fesetexceptflag( const fexcept_t * flagp, int excepts ); |
Restaure l'état des indicateurs à partir d'une valeur précédemment sauvegardée. | C99 |
int fetestexcept( int excepts ); |
Teste les indicateurs actuellement levés. | C99 |
int fetestexceptflag( const fexcept_t * flagp, int excepts ); |
Teste des indicateurs contenus dans une sauvegarde de type fexcept_t. |
C23 |
Le programme suivant efface les indicateurs, provoque une division par zéro en virgule flottante, puis vérifie si l'indicateur correspondant a bien été levé.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
#include <fenv.h> #include <stdio.h> #pragma STDC FENV_ACCESS ON int main() { volatile double zero = 0.0; feclearexcept( FE_ALL_EXCEPT ); volatile double value = 1.0 / zero; (void) value; if ( fetestexcept( FE_DIVBYZERO ) ) { printf( "Division par zero detectee\n" ); } return 0; } |
Une exécution possible produira le résultat suivant.
Division par zero detectee
Le bloc suivant montre comment sauvegarder un état d'exception avec fexcept_t, puis le restaurer ensuite.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
#include <fenv.h> #include <stdio.h> #pragma STDC FENV_ACCESS ON int main() { fexcept_t savedFlags; feclearexcept( FE_ALL_EXCEPT ); feraiseexcept( FE_OVERFLOW ); fegetexceptflag( &savedFlags, FE_OVERFLOW ); feclearexcept( FE_ALL_EXCEPT ); printf( "Apres effacement : %d\n", fetestexcept( FE_OVERFLOW ) != 0 ); fesetexceptflag( &savedFlags, FE_OVERFLOW ); printf( "Apres restauration : %d\n", fetestexcept( FE_OVERFLOW ) != 0 ); return 0; } |
Voici le résultat produit par ce second exemple.
Apres effacement : 0 Apres restauration : 1
-lm, car les
fonctions liées à l'environnement flottant peuvent être fournies avec la librairie mathématique.
Améliorations / Corrections
Vous avez des améliorations (ou des corrections) à proposer pour ce document : je vous remerçie par avance de m'en faire part, cela m'aide à améliorer le site.
Emplacement :
Description des améliorations :