GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Verhindern des C-Integer-Überlaufs

In C ist die gewünschte Header-Datei <stdint.h> und die Konstante ist 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");
}

Für C++ können Sie eine beliebige Anzahl von Lösungen verwenden, die Sie hier finden:Was ist das C++-Äquivalent von UINT32_MAX?


Ich habe festgestellt, dass die allgemeinste Lösung darin besteht, zu prüfen, ob der inkrementierte Wert tatsächlich größer als der vorherige Wert ist oder ob der dekrementierte Wert kleiner als der vorherige Wert ist. Dies funktioniert nur, wenn der Wert unsigned ist , unabhängig von der Größe der Variablen, und ist so ziemlich portabel, wie es C-Code je bekommen kann.

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

Beachten Sie, dass der Code möglicherweise mit signierten Werten funktioniert , aber gemäß dem C-Standard wäre dies ein undefiniertes Verhalten, und die Compiler können if (value + 1 > value) ... ersetzen mit if (1) ... . Das sollten Sie nicht Verwenden Sie diesen Code mit signierten Werten, es sei denn, Sie haben einen Prozess eingerichtet, um den generierten Objektcode zu prüfen, nachdem er verknüpft wurde .

Mit gcc und clang müssten Sie -fwrapv hinzufügen Option, um diesen Code für signierte Werte arbeiten zu lassen; bei anderen Compilern kann Ihre Laufleistung variieren.

Ein sinnvoller Weg, dies zu tun, besteht darin, typspezifisch zu sein und Konstanten aus limits.h zu verwenden . Zum Beispiel:

#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;
  }
}

Vielleicht suchen Sie nach <limits> :http://www.cplusplus.com/reference/limits/numeric_limits/

Sie können so etwas tun, um zu bekommen, was Sie wollen:

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

Sie haben auch diesen <cstdint> :http://www.cplusplus.com/reference/cstdint/

UINTN_MAX:Maximalwert des vorzeichenlosen Typs mit exakter Breite (genau 2^N-1)


Linux
  1. Verhindern, dass ein Bash-Skript gleichzeitig ausgeführt wird

  2. Runden Sie eine geteilte Zahl in Bash

  3. Verwendung von awk mit Spaltenwertbedingungen

  4. Standardmäßiges Arp-Cache-Timeout

  5. Rückgabewert der Timeout-Funktion

So-notify – Ein Stack Overflow Question Notifier

os.MkDir und os.MkDirAll Berechtigungswert?

Rückgabewert von x =os.system(..)

Kodierung von ID3-Tags reparieren

Wie füge ich Benutzer einer anderen Benutzergruppe hinzu?

Was ist eine Auflösung von Jiffie im Linux-Kernel