Как предотвратить целочисленное переполнение при использовании C или C ++? - PullRequest
1 голос
/ 09 августа 2011

http://ideone.com/hANuZ

#include <stdio.h>
int main(int argc, char *argv[]) {
    /**
     * Prints out powers of 2 for 32 iterations.
     */
    int iterations = 0;
    int value = 1;
    while (iterations <= 32) {
        // Prints in this format: iterations    2^n    value
        printf("%d\t2^%d\t%d", iterations, iterations, value);
        switch (iterations) {
          case 8:
          case 16:
          case 32:
              printf("\t\t%d bit\n", iterations);
              break;
          default:
              printf("\n");
              break;
        }
      value *= 2;
      ++iterations;
    }
    return 0;
}

Когда я компилирую и запускаю этот фрагмент кода, странные вещи случаются, когда я печатаю 'значение' после того, как оно больше 2 ^ 30, даже когда я объявляю его какбез знака долго.

Что мне делать?Я просто новичок.: - (

Ответы [ 4 ]

4 голосов
/ 09 августа 2011

Вы печатаете это как целое число со знаком.попробуйте использовать строку формата

"%u\t2^%u\t%u"

. Проверьте в документации printf все коды форматирования и что они делают.%u для unsigned int.unsigned long обычно %lu

1 голос
/ 09 августа 2011

Ради интереса, я немного изменил ваш пример кода для ясности

#include <stdio.h>

int bitcount(unsigned long i) {
   int count = 0;
   while (i > 0) {
      count++;
      i>>=1;
   }
   return count;
}

int main(int argc, char *argv[]) {
   /**
    * Prints out powers of 2 for 32 iterations.
    */
   int iterations = 0;
   int value = 1;
   while (iterations <= 32) {
      // Prints in this format: iterations    2^n    value
      printf("%d\t2^%u\t%u\t\t%d bit\n", iterations+1, iterations, value, bitcount(value));
      value *= 2;
      ++iterations;
   }
   return 0;
}

Вы заметите, что 127 - это 8 bit, а 256 - это 9 bit. Это потому что

127 =   1000 0000
256 = 1 0000 0000

Также 2^32 - это 0, потому что

2^32 = 1 0000 0000 ... 0000 0000       (overflow for int)
     =   0000 0000 ... 0000 0000 = 0   (only the first 32 bits are preserved)
1 голос
/ 09 августа 2011

Простой ответ - попытаться объявить его как unsigned long long, который больше 32 бит (минимум 64 бита согласно стандарту, thx @caf).

При работе с типами, для которых важен определенный размер, следует использовать тип с известным размером, например int64_t.

0 голосов
/ 09 августа 2011

Если вам нужна целочисленная точность, вам нужно использовать внешнюю библиотеку для больших чисел.Для C GMP http://gmplib.org/ - это хорошо известная библиотека.Если вам не нужна целочисленная точность, просто используйте число с плавающей запятой или двойное число.

Если вам интересно, на чем основаны ограничения для типов, эта страница хорошо подходит для чтения http://www.lix.polytechnique.fr/~liberti/public/computing/prog/c/C/CONCEPT/data_types.html.

...