0

I have a program that grabs a user input number and adds the appropriate ending (1st, 11th, 312th, etc) So I gave it to my friend to find bugs/ break it. The code is

    int number;
    printf("\n\nNumber to end?: ");
    scanf("%d",&number);
    getchar();
    numberEnder(number);

when 098856854345712355 was input, scanf passed 115573475 to the rest of the program. Why? 115573475 is less than the max for an int.

Lost Odinson
  • 418
  • 1
  • 5
  • 14
  • Where exacltly is 115573475 in input – coder hacker May 07 '14 at 04:02
  • where is your numberEnder Function's Code????? – Prashant Anuragi May 07 '14 at 04:05
  • @user2848254 Why would that matter? The issue occurs immediately after `scanf` as far as I can tell. – shree.pat18 May 07 '14 at 04:06
  • 115573475 is 98856854345712355 mod (2^32). This is not behaviour you should rely on. The behaviour is undefined by the C standard, which means that the compiler is allowed to just output code that works for valid inputs, and not care about what happens when invalid inputs are given. – M.M May 07 '14 at 04:15
  • 115573475 is stored in 'int number' after scanf reads 098856854345712355. – Lost Odinson May 07 '14 at 04:17
  • @MattMcNabb Do you have a reference for your "undefined behavior" comment? – ooga May 07 '14 at 04:17
  • @ooga ,C99 7.19.6.2p10 "If...the result of the conversion cannot be represented in the object, the behaviour is undefined." – M.M May 07 '14 at 04:30
  • there's some discussion [here](https://groups.google.com/forum/#!topic/comp.std.c/03tnRCrdYOU) along with the behaviour of various compilers; I concur with @KeithThompson 's analysis – M.M May 07 '14 at 04:32

3 Answers3

4

INT_MAX is typically (2^31) -1 which is ~2 billion... ... if you look at 98856854345712355 & 0xffffffff you will find that it is 115573475

Grady Player
  • 14,399
  • 2
  • 48
  • 76
3

The C99 standard states in the fscanf section (7.19.6.2-10):

...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 [emphasis added].

This is true in C11 as well, though fscanf is in a different section (7.21.6.2-10).

You can read more about undefined behavior in this excellent answer, but it basically means the standard doesn't require anything of the implementation. Following from that, you shouldn't rely on the fact that today scanf uses the lower bits of the number because tomorrow it could use the high bits, INT_MAX, or anything else.

Community
  • 1
  • 1
Matt Eckert
  • 1,946
  • 14
  • 16
  • this is absolutely true in theory... but the second that I discover that my std library replaces overflows with 0xdeadbeef is the day I find a new library... – Grady Player May 07 '14 at 14:46
2

098856854345712355 is too big of a number for int.

long long number;
printf("\n\nNumber to end?: ");
scanf("%lld",&number);
getchar();
numberEnder(number);

The answer to why you get a specific garbage answer is GIGO. The standard doesn't specify the result for bad input and it's implementation specific. I would hazard a guess that if you apply a 32 bit mask to the input, that's the number you would get.


Just out of curiosity, I looked up an implementation of scanf.

It boils down to

…
                                res = strtoq(buf, (char **)NULL, base);
…
                                    *va_arg(ap, long *) = res;
…

Which should truncate off the high-bits in the cast. That would support the bit-mask guess, but it would only be the case for this implementation.

Jeffery Thomas
  • 42,202
  • 8
  • 92
  • 117