3 votes

Utilisation des fonctions de débordement intégrées avec les types uint64_t

Je suis en train d'écrire un programme qui fait un usage intensif de la fonction uint64_t afin d'améliorer la compatibilité entre les plates-formes. Il se trouve qu'il y a beaucoup de possibilités de débordements dans mon programme, c'est pourquoi je veux utiliser le type fonctions de débordement intégrées dans gcc .

Malheureusement, ils ne sont définis que sur int s, long int s, long long int et ainsi de suite. Les uintX_t garantissent d'avoir toujours une taille de X bits, ce qui n'est pas le cas pour les types, par exemple, a long int n'est pas garanti en 64 bits. Cela me fait penser que les fonctions de débordement intégrées ne peuvent pas être utilisées ici.

Comment résoudre ce problème maintenant ?

J'ai deux approches :

  1. en utilisant le UINT64_MAX constante de stdint.h et de faire moi-même la prédiction de débordement. Cependant, je ne suis pas partisan de "réinventer la roue".

  2. en utilisant l'exemple __builtin_add_overflow_p pour ne vérifier que le débordement. Cependant, je ne suis pas sûr à 100 % qu'ils puissent être appliqués à la fonction uint64_t .

Quelle est la meilleure façon de procéder ? Suis-je en train de superviser quelque chose d'évident ?

4voto

chux Points 13185

Utilisation des fonctions de débordement intégrées avec uint64_t
... pour utiliser le fonctions de débordement intégrées dans gcc .

Pour former votre propre builtin_uadd64_overflow() sans "réinventer la roue", utiliser _Generic pour piloter la sélection de la fonction.

#define builtin_uadd64_overflow(a,b,r) _Generic(*(r), \
  unsigned: __builtin_uadd_overflow, \
  unsigned long: __builtin_uaddl_overflow, \
  unsigned long long: __builtin_uaddll_overflow \
  )(a,b,r)

1voto

Ctx Points 4379

Le dépassement de capacité non signé est un comportement défini par la norme C (§6.2.5/9).

Un calcul impliquant des opérandes non signés ne peut jamais dépasser, car un résultat qui ne peut pas être représenté par le type d'entier non signé résultant est réduit modulo le nombre qui est supérieur d'une unité à la plus grande valeur qui peut être représentée par le type résultant.

Ainsi, lorsque vous avez un ajout comme ;

uint64_t a, b, c;

c = a + b;

vous pouvez vérifier si l'opération a débordé en testant

int overflowed = c < a || c < b;

Bien entendu, vous pouvez l'intégrer dans une fonction si vous le souhaitez.

1voto

supercat Points 25534

Les fonctions suivantes devraient fonctionner assez bien pour les objets de type int o long long ; sur les plates-formes 32 bits, l'option int seront beaucoup plus efficaces que les approches utilisant les fonctions long long ; sur les plates-formes 64 bits, l'option long long seront aussi efficaces que les fonctions int des personnes.

int safe_add1(int  *value, int  delta) {
    int val = *value;
    int sum = delta+(unsigned int)val;
    if (((sum ^ val) & (sum ^ delta)) < 0)
        return -1;
    *value = sum;
    return 0;
}
int safe_add2(long long  *value, long long  delta) {
    long long val = *value;
    long long sum = delta+(unsigned long long)val;
    if (((sum ^ val) & (sum ^ delta)) < 0)
        return -1;
    *value = sum;
    return 0;
}

Il convient de noter qu'une protection vraiment efficace contre les débordements nécessiterait dans de nombreux cas qu'un compilateur utilise les débordements d'entiers comme une invitation à mettre en œuvre une extension conforme qui définirait la sémantique des débordements d'entiers d'une manière suffisamment stricte pour répondre aux exigences du programme, mais suffisamment lâche pour permettre des optimisations. Par exemple, si un programme veut calculer x+y > z tout en veillant à ce qu'il n'y ait pas de débordements qui donneraient lieu à des numériquement erroné ne sont pas détectés, et si un compilateur sait que les x y z seront égales, la meilleure façon de répondre aux exigences serait de calculer y > 0 puisque ce comportement serait numériquement correct si oui ou non x+y a pu être calculée sans débordement.

Malheureusement, à moins que les compilateurs ne fournissent des extensions pour reconnaître ces constructions, il n'y aura aucun moyen d'écrire un code de contrôle de débordement particulièrement efficace.

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