#include<stdio.h>
main()
{
unsigned int num;
printf("enter the number:\n");
scanf("%u",&num);//4294967299 if i'm scanning more than 4G its not scanning
printf("after scanning num=%u\n",num);// 4294967295 why its giving same 4G
/* unsigned char ch;
printf("enter the character:\n");
scanf("%d",&ch);// if i/p=257 so its follow circulation
printf("after scanning ch=%d\n",ch);// 1 its okk why not in int ..
*/
}
Why is circulation not following while scanning input via scanf()
, why is it following in case of char
?
From this scanf
(and family) reference for the "%u"
format:
The format of the number is the same as expected by strtoul()
with the value 0
for the base argument (base is determined by the first characters parsed)
Then we go to the strtoul
function, and read about the returned value:
Integer value corresponding to the contents of str on success. If the converted value falls out of range of corresponding return type, range error occurs and ULONG_MAX
or ULLONG_MAX
is returned. If no conversion can be performed, 0
is returned.
From this we can see that if you enter a too large value for the scanf
"%u"
format, then the result will be ULONG_MAX
converted to unsigned int
. However the result will differ on systems where sizeof(unsigned long) > sizeof(unsigned int)
. See below for information about that.
It should be noted that on platforms with 64-bit unsigned long
and 32-bit unsigned int
, a value that is valid in the range of unsigned long
will not be converted to e.g. UINT_MAX
, instead it will be converted using modulo arithmetic as detailed here.
Lets take the value like 4294967299
. It is to big to fit in a 32-bit unsigned int
, but fits very well in a 64-bit unsigned long
. Therefore the call to strtoul
will not return ULONG_MAX
, but the value 4294967299
. Using the standard conversion rules (linked to above), this will result in an unsigned int
value of 3
.
The C11 standard draft n1570 7.21.6.2 says the following
paragraph 10
[...] the input item [...] is converted to a type appropriate to the conversion specifier. If the input item is not a matching sequence, the execution of the directive fails: this condition is a matching failure. Unless assignment suppression was indicated by a *
, the result of the conversion is placed in the object pointed to by the first argument following the format argument that has not already received a conversion result. 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, the word "conversion" here is used for string => result data type conversion, it cannot be understood to mean integer conversions. As the string "4294967299"
converted to a decimal integer is not representable in an object of type unsigned int
that is 32-bit wide, the reading of the standard says that the behaviour is undefined, i.e.
behavior, upon use of a nonportable or erroneous program construct or of erroneous data, for which this International Standard imposes no requirements
Thus, the answer to your question is that the C standard doesn't state the behaviour in this case, and the behaviour you see is the one exhibited by your compiler and C library implementation, and is not portable; on other platforms the possible behaviours might include:
ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message).