Когда в последнее время отвечая на другой вопрос, я обнаружил проблему с кодом вроде:
int n;
scanf ("%d", &n);
С strtol
вы можете обнаружить переполнение, потому что в этом случае максимальное допустимое значение вставляется в n
и errno
установлено для указания переполнения в соответствии с 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 (в соответствии с типом возврата и знаком значения, если таковые имеются) и значением макрос ERANGE хранится в errno.
Однако в разделах стандарта, касающихся scanf
, в частности C11 7.21.6.2 The fscanf function /10
, мы видим:
Если этот объект не имеет соответствующего типа или если результат преобразования не может быть представлен в объекте, поведение undefined.
Теперь для меня это означает, что любое значение может быть возвращено, и нет упоминания о том, что errno
установлено на что угодно. Это обнаружилось, потому что искатель связанного вопроса выше входил 9,999,999,999
в 32-разрядный int
и возвращался 1,410,065,407
, значение 233
было слишком маленьким, указывая, что оно просто было обернуто на пределе тип.
Когда я попробовал, я вернул 2,147,483,647
, максимально возможное 32-разрядное значение без знака.
Итак, мой вопрос таков. Как вы обнаруживаете интегральное переполнение портативным способом при использовании семейства функций scanf
? Возможно ли это?
Теперь я должен упомянуть, что в моей системе (Debian 7) errno
на самом деле установлен в ERANGE
в этих обстоятельствах, но я не могу найти ничего в стандарте, который это задает. Кроме того, возвращаемое значение из scanf
равно 1
, что указывает на успех при сканировании элемента.