2
#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?

mkrieger1
  • 19,194
  • 5
  • 54
  • 65
Achal
  • 11,821
  • 2
  • 15
  • 37
  • @JoachimPileborg But here they are `unsigned type` so why it will be unspecified behaviour . – ameyCU Sep 18 '15 at 09:29
  • at compile time if i'm taking more than range , value its giving correctly but why not at run time ? – Achal Sep 18 '15 at 09:40
  • 1
    Entering an integer literal that the compiler will parse is one thing, the `scanf` function is a completely other thing. Those two and their parsing is not related. – Some programmer dude Sep 18 '15 at 09:42

2 Answers2

6

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).

-4

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.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • 3
    ["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.**"](http://port70.net/~nsz/c/c11/n1570.html#7.21.6.2p10) (emphasis added). `%u` expects the same **format** as a [subject sequence](http://port70.net/~nsz/c/c11/n1570.html#7.22.1.4p3) of `strtoul` with base 10, but the subject sequence is just that: format. It does not guarantee anything about the value, at least to my reading of the standard. Please feel free to correct my reading as necessary. – Ilja Everilä Feb 10 '17 at 08:58
  • @SurajJain Because conversions from a large integer type to a smaller integer type is performed using modulo arithmetic. If, for example, `unsigned long` is 64 bits and `unsigned int` is 32 bits, the result is what is expected. [Read more about integer conversions here](http://en.cppreference.com/w/c/language/conversion#Integer_conversions). – Some programmer dude Feb 10 '17 at 09:15
  • @AnttiHaapala Not really, it just follows the standard integer conversion rules. The problem with large number as shown in the comment by Suraj Jain is when `sizeof(unsigned long) > sizeof(unsigned it)`. The conversion is correct. – Some programmer dude Feb 10 '17 at 09:20
  • @IljaEverilä And that's why I have updated the answer to include 64-bit `unsigned long` being converted to 32-bit `unsigned int`. The answer was perfectly fine for both types being 32 bits, and now it includes information about what happens if they are not. – Some programmer dude Feb 10 '17 at 09:31
  • 2
    Why include bits at all. There's no need, except for the basic "your system may have an `unsigned int` of 32 bits and thus...". The answer is still both wrong and convoluted. It mixes behaviour of `strtoul` with `scanf("%u", ...)` that does not apply. Only the format of the subject sequence with base 10 applies. – Ilja Everilä Feb 10 '17 at 09:33
  • 1
    One thing to note from the standard that it uses `strtoul` as the "formatting" example for `u`; even when we know that a conversion specifier `ll` flags, i.e. `%llu` cannot be necessarily presented by `strtoul`. – Antti Haapala -- Слава Україні Feb 10 '17 at 09:58
  • Maybe your answer is wrong please see here http://stackoverflow.com/questions/42162536/what-happens-if-i-input-number-more-than-the-range-of-data-type-in-c – Suraj Jain Feb 10 '17 at 20:02