GNU/Linux >> Linux Esercitazione >  >> Linux

Prevenire l'overflow di numeri interi C

In C il file di intestazione che vuoi è <stdint.h> e la costante è 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");
}

Per C++ puoi usare qualsiasi numero di soluzioni trovate qui:Qual è l'equivalente C++ di UINT32_MAX?


Ho scoperto che la soluzione più generale è verificare se il valore incrementato è effettivamente maggiore del valore precedente o se il valore decrementato è inferiore al valore precedente. Funziona solo se il valore non è firmato , indipendentemente dalla dimensione della variabile, ed è praticamente portabile quanto il codice C può mai ottenere.

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

Tieni presente che il codice può capitare di funzionare con valori firmati , ma secondo lo standard C questo sarebbe un comportamento indefinito e i compilatori sono liberi di sostituire if (value + 1 > value) ... con if (1) ... . Non dovresti usa questo codice con valori firmati a meno che tu non abbia un processo in atto per controllare il codice oggetto generato dopo che è stato collegato .

Con gcc e clang, dovresti aggiungere -fwrapv opzione per far funzionare questo codice per i valori con segno; con altri compilatori il tuo chilometraggio può variare.

Un modo sensato per farlo è essere specifici del tipo e usare le costanti da limits.h . Ad esempio:

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

Forse stai cercando <limits> :http://www.cplusplus.com/reference/limits/numeric_limits/

Puoi fare qualcosa di simile per ottenere quello che vuoi:

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

Hai anche questo <cstdint> :http://www.cplusplus.com/reference/cstdint/

UINTN_MAX:valore massimo del tipo senza segno a larghezza esatta (esattamente 2^N-1)


Linux
  1. Il valore massimo dell'ID di processo?

  2. Utilizzare Ts senza perdere il valore di uscita?

  3. Ordina per valore esadecimale?

  4. Arrotonda un numero diviso in Bash

  5. Timeout predefinito della cache arp

So-notify:un notificatore di domande sull'overflow dello stack

Valore di autorizzazione os.MkDir e os.MkDirAll?

Valore di ritorno di x =os.system(..)

Ripara la codifica dei tag ID3

Come posso aggiungere utenti a un altro gruppo di utenti?

qual è una risoluzione di jiffie nel kernel Linux