GNU/Linux >> Tutoriels Linux >  >> Linux

Empêcher le débordement d'entier C

En C, le fichier d'en-tête que vous voulez est <stdint.h> et la constante est UINT32_MAX

static void update_value(char op)
{
    if (op == '+')
        if ( value < (UINT32_MAX - 1))
            value++;    // uint32_t global value
        else
            printf("too big!\n");
    else
       if (value > 0)
           value--;
       else
           printf("too small!\n");
}

Pour C++, vous pouvez utiliser n'importe quel nombre de solutions trouvées ici :Quel est l'équivalent C++ de UINT32_MAX ?


J'ai trouvé que la solution la plus générale consiste à vérifier si la valeur incrémentée est en fait supérieure à la valeur précédente, ou si la valeur décrémentée est inférieure à la valeur précédente. Cela ne fonctionne que si la valeur n'est pas signée , indépendamment de la taille de la variable, et est à peu près aussi portable que le code C ne l'est jamais.

static void update_value(char op)
{
  if (op == '+') {
    if (value + 1 > value) value ++;
  } else {
    if (value - 1 < value) value --;
  }
}

Notez que le code peut fonctionner avec des valeurs signées , mais selon la norme C, ce serait un comportement indéfini, et les compilateurs sont libres de remplacer if (value + 1 > value) ... avec if (1) ... . Vous ne devriez pas utilisez ce code avec des valeurs signées, sauf si vous avez mis en place un processus pour auditer le code objet généré après qu'il a été lié .

Avec gcc et clang, vous devez ajouter -fwrapv option pour laisser ce code fonctionner pour les valeurs signées ; avec d'autres compilateurs, votre kilométrage peut varier.

Une façon sensée de le faire est d'être spécifique au type et d'utiliser des constantes de limits.h . Par exemple :

#include "limits.h"

static void update_int(char op, int *value)
{
  int val = *value; // ignoring NULL pointer dereference

  if (op == '+') {
    if (val != INT_MAX) *value = val + 1;
  } else {
    if (val != INT_MIN) *value = val - 1;
  }
}

static void update_int(char op, unsigned int *value)
{
  unsigned int val = *value; // ignoring NULL pointer dereference

  if (op == '+') {
    if (val != UINT_MAX) *value = val + 1;
  } else {
    if (val != UINT_MIN) *value = val - 1;
  }
}

Peut-être recherchez-vous <limits> :http://www.cplusplus.com/reference/limits/numeric_limits/

Vous pouvez faire quelque chose comme ceci pour obtenir ce que vous voulez :

unsigned int n = numeric_limits<unsigned int>::max()

Vous avez aussi ce <cstdint> :http://www.cplusplus.com/reference/cstdint/

UINTN_MAX :valeur maximale du type non signé à largeur exacte (exactement 2^N-1)


Linux
  1. La valeur maximale de l'ID de processus ?

  2. Utiliser Ts sans perdre la valeur de sortie ?

  3. Comment ajouter des utilisateurs à un autre groupe d'utilisateurs ?

  4. qu'est-ce qu'une résolution de jiffie dans le noyau Linux

  5. Comment la priorité du processus est-elle calculée ?

So-notify - Un notificateur de question de débordement de pile

Valeur d'autorisation os.MkDir et os.MkDirAll ?

Valeur de retour de x =os.system(..)

Réparer l'encodage des balises ID3

Délai d'expiration du cache arp par défaut

Valeur de retour de la fonction de temporisation