2014-10-14 5 views
0

Я экспериментирую как с неподписанными типами данных int, так и с основными параметрами метода в простых программах на C. В качестве эксперимента я написал программу, которая принимает номер int из командной строки в качестве параметра в основной метод и суммирует каждое целое число между этим числом и 0.C Манипуляция без знака Ints - Целочисленное переполнение

E.g. Программа вычисляет F (N) = (1 + 2 + 3 ... + п) справедливо при п> 0

#include <stdio.h> 
#include <stdlib.h> 

const unsigned int MAX_NUM = 92681; //Max input that will avoid int overflow later on 

unsigned int sum(unsigned int x); 

int main(int argc, char *argv[]) { 

    unsigned int input = atoi(argv[1]); 

    if (input < 0 || input > MAX_NUM) { 
     printf("Invalid input! Input must be less than 92682\n"); 
     exit(0); //If input > MAX_NUM, quit program 
    } 

    unsigned int result = sum(input); 

    printf("Sum to %d = %d\n", input, result); 

    return 0; 
} 

unsigned int sum(unsigned int x) { 
    unsigned int sum = 0; 
    unsigned int y; 
    for (y = 0; y <= x; y++) { 
     sum += y; 
     printf("Current sum:\t%u\n",sum); 
    } 
    return sum; 
} 

первая вещь, которую я начал замечать было Целочисленное переполнение при е (п)> 2147483648 - aka максимальное значение для подписанного int.

Я нашел математически максимальные значения вручную, для которых результаты, сгенерированные моей программой, были бы действительными (например, перед переполнением целых чисел), равными 65535 для подписанных int и 92681 для неподписанных целых чисел.

Запуск программы для подписанных ints дал ожидаемые результаты - на 65535 очень большое положительное число стало очень большим отрицательным числом при переполнении целого числа.

Затем я прошел и изменил каждый «int» на «unsigned int». Несмотря на это целочисленное переполнение происходит, как если бы они были подписаны, а не без знака.

Мой вопрос: а) Почему это? б) Как я могу сделать это так, чтобы мой ответ мог использовать весь диапазон беззнакового int i.e от 0 до (2^32) - 1 (поскольку мне не нужны отрицательные значения!).

Большое спасибо!

+1

Совет от Гаусса: n * (n-1)/2. –

+1

То, как я рассчитал максимальные значения, т.е. 2^32 = n * (n-1)/2 – davidhood2

ответ

4

Вы забыли изменить окончательные форматы printf с подписью на неподписанные.

Изменение:

printf("Sum to %d = %d\n", input, result); 

к:

printf("Sum to %u = %u\n", input, result); 
       ^^ ^^ 

Обратите внимание, что включение предупреждений компилятора (например gcc -Wall ...) бы предупредил вас об этом. Всегда включайте предупреждения компилятора и всегда учитывайте их.

+1

О, вау, я чувствую себя глупо! Спасибо – davidhood2

+0

Ну, если это учит вас всегда включать предупреждения компилятора, то это будет стоить того. ;-) –

+1

@PaulR Не уверен, что использует OP, но я хочу, чтобы MSVC, наконец, начал выдавать предупреждения для этого ... '/ analysis' kinda делает, но ужасно медленный и не предупреждает об этом конкретном случае (несоответствие подписанного/неподписанного). Ну, по крайней мере, мы наконец получим C99 (sn) 'printf' в версии« 14 », sigh ...;) – user2802841

 Смежные вопросы

  • Нет связанных вопросов^_^