12
votes

Est-il possible d'accéder au registre du drapeau de trop-plein dans une CPU avec C ++?

Après avoir effectué une opération mathématique, en multipliant deux entiers, est-il possible d'accéder au registre du drapeau de trop-plein dans une CPU avec C ++? Sinon, quelles sont les autres moyens rapides de vérifier un débordement?


5 commentaires

Cochez cette case Stackoverflow. com / questions / 199333 / ...


@Acrilige Merci, qui répond à la deuxième partie de ma question, une idée de la manière de vérifier le débordement après avoir effectué les calculs?


Pour des raisons évidentes, il est impossible d'accéder directement au registre des drapeau de débordement d'une manière standard et portable. Cependant, vous pouvez déterminer si une opération déborde d'un peu de travail, et il existe des moyens de vérifier cela ou de détecter des débordements de manière non portable non standard.


Pourquoi ne pouvez-vous pas vérifier le débordement avant des calculs?


Divisez le résultat par le multiplicand. Si vous n'obtenez pas le multiplicateur de retour, alors il déborde.


5 Réponses :


12
votes

Non, généralement c'est impossible. Certains processeurs n'ont même pas un tel drapeau (par exemple MIPS).

the lien fourni dans l'un des commentaires sera vous donner des idées sur la façon dont vous pouvez faire des chèques de débordement.

N'oubliez pas que les débordements d'entier signés en C et C ++ ont signé causant un comportement indéfini et légalement, vous ne pouvez pas effectuer des contrôles de débordement après le fait. Vous devez soit utiliser des arithmétiques non signés ou faire les chèques avant les opérations arithmétiques.


0 commentaires

8
votes

Je recommande cette lecture dans chaque cas approprié. De Optimisation du logiciel en C ++ -

Le débordement entier est un autre problème de sécurité. La norme C officielle dit que le comportement des entiers signés en cas de débordement est "indéfini". Cela permet au compilateur d'ignorer le débordement ou d'assumer que cela ne se produit pas. Dans le cas du compilateur GNU, l'hypothèse ce débordement entier signé ne se produit pas a malheureux conséquence qu'il permet au compilateur d'optimiser un débordement Chèque. Il existe un certain nombre de remèdes possibles contre ce problème: (1) Vérifiez que le débordement avant qu'il ne se produise, (2) utilise des entiers non signés - ils sont garantis pour envelopper, (3) piéger le débordement entier avec le Option -ftrapv , mais c'est extrêmement inefficace, (4) obtenir un compilateur Avertissement pour ces optimisations avec option -WStrict-Overflow = 2 ou (5) Faites le comportement de trop-plein bien défini avec l'option -fwrapv ou -fno-strict-overflow .


0 commentaires

0
votes

Ce n'est probablement pas ce que vous voulez faire pour deux raisons:

  1. Tous les CPU n'ont pas un drapeau de débordement
  2. Utilisation C ++, il n'y a aucun moyen d'accéder au drapeau de trop-plein

    Le débordement des conseils de contrôle que les personnes ont affiché avant d'être utiles.

    Si vous voulez vraiment très écrire un code rapide qui multiplie deux entiers et vérifie le drapeau de débordement, vous devrez utiliser l'assemblage. Si vous voulez quelques exemples pour x86, demandez-vous à


0 commentaires

1
votes

Vous devez faire l'opération et vérifier le débit de débordement dans l'assemblage en ligne. Vous pouvez le faire et passer à une étiquette sur le débordement ou (plus généralement mais moins efficacement) définir une variable si elle débordée.


1 commentaires

C'est étrange pour moi que personne d'autre a mentionné cette option. Alors que l'assemblage en ligne n'est pas strictement C ++, c'est une option absolument viable pour quiconque posant cette question. Il y a bien sûr la limitation que cela ne compilait pas pour toutes les architectures, mais cela dépend de la possibilité de décider si cela est important ou non.



1
votes

non. Meilleure approche pour vérifier à l'avance comme ici

Si non, quelles sont les autres moyens rapides de vérifier un débordement?

Si vous devez tester après l'opération, vous pouvez utiliser une représentation de point flottante (double précision) - chaque entier 32 bits peut être représenté exactement comme un nombre de points flottants. Si toutes les machines que vous ciblez le support IEEE (qui est probablement le cas si vous n'avez pas à envisager de prendre en compte les ordinateurs centraux), vous pouvez simplement effectuer les opérations, puis utiliser Isfinite ou ISINF sur les résultats. Rapide (en termes d'efforts de programmeur) La voie est la suivante: la norme IEEE pour l'arithmétique de point flottant (IEEE 754) définit cinq exceptions près, chacune de la valeur par défaut et dispose d'un indicateur d'état correspondant qui (sauf dans certains cas de sousfaction) est soulevé lorsque l'exception se produit. Les cinq exceptions possibles sont:

  • Fonctionnement non valide: mathématiquement indéfini, par exemple, la racine carrée d'un nombre négatif. Par défaut, renvoie QNAN.
  • division par zéro: une opération sur les opérandes finies donne un résultat exact infini, par exemple 1/0 ou journal (0). Par défaut, renvoie ± Infinity.
  • Overflow: Un résultat est trop grand pour être représenté correctement (c'est-à-dire son exposant avec une gamme d'exposant sans bornes serait plus grande que Emax). Par défaut, renvoie ± Infinity pour les modes ronds à la plus proche (et suit les règles d'arrondi pour les modes d'arrondi dirigés).
  • Underflow: un résultat est très petit (en dehors de la plage normale) et est inexact. Par défaut, renvoie un sous-formel ou zéro (suivant les règles d'arrondi).
  • inexact: le résultat exact (c'est-à-dire non fini) n'est pas représentable exactement. Par défaut, renvoie le résultat correctement arrondi.

9 commentaires

Notez que cette question est étiquetée integer-overflow et est sur le débordement entier signé. PAS FP Overflow to + -inf. Vous peut Accéder aux indicateurs FP via fenv : EN.CPPREFEREFERCE.COM/W/C/Numeric/fenv . Fetestexcept (Fe_Overflow) Vérifie le drapeau de débordement de la FP. (Ne fonctionne que si vous utilisez #pragma stdc fenv_access sur ou des options de ligne de commande pour certains compilateurs. EN.CPPRAFERFERFERATION.COM/W/C/numérique/fenv/fetestexcept a un exemple.)


Je vois - chaque entier peut être représenté comme un numéro de point flottant et il n'y a pas d'autre manière rapide. Sauf vérifier à l'avance.


double peut représenter tous les int32_t mais pas tous les intz_t . Donc oui, vous pouvez vérifier la plage d'un double avant de reculer sur int . C'est difficilement efficace, alors idk que votre point est. Certaines machines auront un double de 80 bits ou plus large qui peut représenter chaque intz_t , mais de nombreuses implémentations C ++ n'ont que 64 bits FP. En outre, le débordement de FP est hors de propos de ce problème (sauf si vous effectuez plusieurs multiplies multiples qui produisent réellement un débordement de FP).


Le nombre de points flottants avec double précision est limité par 10 ^ 308. Plus de 10 ^ 64. IEEE 754 est sur une seule et double précision.


Oui, c'est le plus haut niveau fini double , mais le premier entier non représentable-valorisé double est 2 ^ 53 + 1 car il a une mantissée de 53 bits. en.wikipedia.org/wiki/double-precision_floating-point_format . Un 64 bits double peut représenter certains nombres autres que des valeurs possibles de intz_t , par conséquent par le principe du pigeonhole, il doit y avoir des valeurs de intT64_t que Ne pas avoir de Double Modèle de bits pour les représenter. Voir qui est le premier entier qu'un float IEEE 754 est incapable de représenter exactement?


Probablement que vous écrivez. Ensuite, cette approche peut être utilisée pour 32 bitst. Etrange - je suppose que la conversion C # de tout numéro intégral, dont 64 bits, est implicitement convertie en double. Et la conversion implicite ne concerne que de se lancer sans perte d'informations. Mais vous remarquez à propos de MANTISSA probablement correct - il devrait y avoir des lacunes dans la représentation - perdue de précision


Certainement, vous êtes écriture: le principe du pigeonhole peut être étendu aux ensembles en le formant en termes de numéros cardinaux: si la cardinalité de l'ensemble L est supérieure à la cardinalité de la série D, alors il n'y a aucune injection de L à D. 2) Double et long Long (INT64_T) a 2 ^ 64 états. Soit L est défini sur les valeurs longues intz_t possibles et D est défini sur les valeurs doubles possibles (non nan). Certains états en double sont utilisés pour les valeurs de signalisation - la cardinalité de L est donc plus grande que la cardinalité de D et aucune injection de L à D.


Yup, en plus de signaler les nans, double a également beaucoup de valeurs non entières. La moitié des modèles de bits double représentent des valeurs entre -1,0 et +1,0, et il existe de nombreuses valeurs fractionnaires entre les plus petits entiers. (FYI, le mot anglais que vous recherchez ici est "Droite", pas "Ecrire". Prononcé la même chose, orthographié différemment.) Je n'ai pas inventé cette preuve juste maintenant; C'est un fait bien connu. Mais content de pouvoir vous aider et le signaler. Quoi qu'il en soit, vous pouvez aimer RandomAccii.WordPress. COM / 2012/02/25 / ... - Super série d'articles PF


Merci-bons article. Je me souviens de (0..1) - pour la preuve, il suffit de mentionner une cardinalité différente. Aussi, j'avais peur que mon livre C # ait une erreur: "Les conversions implicites sont autorisées lorsque les deux suivantes sont vraies: 1) Le compilateur peut garantir qu'ils réussiront toujours. 2) Aucune information n'est perdue dans la conversion". Mais je n'ai pas remarqué que le livre a notez le livre: "Une mise en garde mineure est que de très grandes valeurs longues perdent une certaine précision lorsqu'elles sont converties en double ... En effet, les types de points flottants ont toujours plus de grandeur que les types intégrés, mais peuvent avoir moins de précision. " Donc, le livre a raison.