9,999,999,999
(десять 9
s) является большим, чтобы вписаться в ваш тип int
данных. Если вы работаете разницу между этим и 1,410,065,407
, вы увидите, что это точная мощность двух (2 быть точным), а это означает, что она обернута вокруг, пока вы сканировали его.
К «завернутые вокруг ", я ссылаюсь на свойство целых чисел, чтобы просто обернуть их с максимальным значением, чтобы стать чем-то неожиданным.
Например, восьмизначное целое число без знака, которое может содержать значения 0..255
, при добавлении одного к переменной, удерживающей 255
, станет нулевым (значения в значении имеют тенденцию обертываться от наибольшего положительного значения до наименьшего отрицательного значения, наименьший смысл, далекий от нуля в этом случае).
Итак, скажем, вы читаете десятичное число, где тип имеет диапазон 0..255
, а строковое представление числа - 456
. Следующий «код» будет примерно, как она работает:
def scanNum(s):
result = 0
for each character c in s:
result = result * 10 + value(c)
return result
- При обработке
4
характера, result
умножается на десять, 0 * 10 = 0
, а затем добавить четыре, давая 4
.
- При обработке символа
5
result
умножается на десять, 4 * 10 = 40
, а затем вы добавляете пять, давая 45
.
- При обработке
6
характера, result
умножаются на десять, 45 * 10 = 450
но, потому что вы можете только представить 0..255
, он оборачивается вокруг, давая вам 450 - 256 = 194
. А затем добавьте шесть, давая 200
.
Вы можете видеть, что разница между тем, что вы хотите и что получаете, очень сильно зависит от диапазона: 456 - 200 = 256
.
Если вы попробуете это с девять9
с (или 999,999,999
, имея в виду наибольшее число представимо с 32-битным дополнением до двух больше на 2,147,483,647
), или использовать тип данных, способный удерживать большее количество, вы» будет, вероятно, найти это нормально:
#include <stdio.h>
#include <stdlib.h>
int main (void) {
long long n;
printf("Enter the number to be checked\n");
scanf("%lld",&n);
printf("%lld\n", n);
return 0;
}
первоначально я думал, что это было неправильно в соответствии со стандартом, так как, согласно C11 7.21.6.2 The fscanf function /12
, оно сдвинуто на strtol
функции:
d Соответствует значению десятичного целого числа, форма которого совпадает с ожидаемым для субъектной последовательности функции strtol со значением 10 для базового аргумента. Соответствующим аргументом должен быть указатель на целое число со знаком.
и функция strtol
, C11 7.22.1.4 The strtol, strtoll, strtoul, and strtoull functions /8
состояния:
Если правильное значение находится вне диапазона представимых значений, LONG_MIN, LONG_MAX, LLONG_MIN, LLONG_MAX, ULONG_MAX или ULLONG_MAX является возврат (в соответствии с тип возврата и знак значения, если таковые имеются).
Но, в действительности, только формат сдвинуто этой функции. результат для fscanf
и его братьев контролируется C11 7.21.6.2 The fscanf function /10
:
Если этот объект не имеет соответствующий тип, или , если результат преобразования не могут быть представлены в объекте, поведение не определено ,
Таким образом, число вы получите обратно, если он находится вне диапазона может быть что угодно, и, на самом деле, учитывая отсутствие ограничений по результатам неопределенного поведения, это может сделать ничего, а не просто возвращение изворотливого результат, в том числе форматирование ваших дисков и сворачивание локального пространства-времени в голые особенности :-)
В этом случае он просто просто переносит значение вокруг как часть процесса сканирования, что является самым простым для кода ,
'void main()' должен быть 'int main (void)'. Если вы узнали 'void main()' из книги, верните свои деньги и пожалотесь издателю. –