When recently answering another question, I discovered a problem with code like:
int n;
scanf ("%d", &n);
With strtol
, you can detect overflow because, in that case, the maximum value allowed is inserted into n
and errno
is set to indicate the overflow, as per C11 7.22.1.4 The strtol, strtoll, strtoul, and strtoull functions /8
:
If the correct value is outside the range of representable values, LONG_MIN, LONG_MAX, LLONG_MIN, LLONG_MAX, ULONG_MAX, or ULLONG_MAX is returned (according to the return type and sign of the value, if any), and the value of the macro ERANGE is stored in errno.
However, in the sections of the standard dealing with scanf
, specifically C11 7.21.6.2 The fscanf function /10
, we see:
If this object does not have an appropriate type, or if the result of the conversion cannot be represented in the object, the behavior is undefined.
Now, to me, that means any value can be returned and there's no mention of errno
being set to anything. This came to light because the asker of the linked question above was entering 9,999,999,999
into a 32-bit int
and getting back 1,410,065,407
, a value 233
too small, indicating it had simply wrapped around at the limit of the type.
When I tried it, I got back 2,147,483,647
, the largest possible 32-bit unsigned value.
So my question is as follows. How do you detect integral overflow in a portable way when using the scanf
family of functions? Is it even possible?
Now I should mention that, on my system (Debian 7), errno
is actually set to ERANGE
in these circumstances but I can find nothing in the standard that mandates this. Additionally, the return value from scanf
is 1
, indicating success in scanning the item.
See Question&Answers more detail:
os