3

I ran this code

#include <stdio.h>
int main()
{
    int u;
    scanf("%d",&u);
    printf("%d\n",u,u);
    return 0;   
}

The following are the inputs and outputs:

input:a output:32765
input:b output:32765
input:c output:32767
input:/ output:32766

Can anyone explain this behaviour?

  • 3
    `scanf` fails, returns 0 and the next statement in your code executes. It would be the same as if the `scanf` line wasn't there. In short, your code invokes Undefined Behavior as you try to print an uninitialized variable – Spikatrix Mar 06 '17 at 11:36

2 Answers2

3

When scanf() reads input it cannot convert according to the specification, it stops scanning and returns the number of successful conversions. In your case, the character remains in the standard input buffer and scanf() returns 0.

Your code has undefined behavior because scanf() fails to convert the input as an integer, leaving u uninitialized. Passing this uninitialized value to printf has undefined behavior. In your case, a somewhat random value is printed, which may be different or not, but any other behavior is possible including a crash.

You must test the return value of scanf() to check if the conversion was successful. Here is a modified version:

#include <stdio.h>

int main(void) {
    int u, res;
    res = scanf("%d", &u);
    if (res == 1) {
        /* conversion succeeded */
        printf("%d\n", u);
    } else
    if (res == 0) {
        /* conversion failed */
        printf("input is not a valid number\n");
    } else {
        /* res must be EOF */
        printf("premature end of file: no input given\n");
    }
    return 0;   
}
chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • I know it is UB, but, what could be the reason the output of the code lurks around `32767`? – Spikatrix Mar 06 '17 at 12:13
  • @CoolGuy: uninitialized variable `u` *happens* to have a value of `32767` sometimes... A side effect f the startup code that left the stack or registers with this contents. Depending on the OS and the startup code, this value may be reproducible or not. Trying to make sense of UB is quite vain, and may require assembly level inspection and some magical skills. – chqrlie Mar 06 '17 at 12:29
2

The behaviour of your program is undefined.

You should check the return value of scanf, which tells you the number of data that are read into the passed arguments. In your case the return value will be zero, as %d cannot be used to read in a char. So u is uninitialised, and therefore its value should not be read.

Note that the fact that you have passed in superfluous parameters to your printf is benign although, formally, such arguments are still evaluated. See Is calling printf with excess arguments undefined behaviour?.

The moral of the story: always inspect the return value of scanf.

Community
  • 1
  • 1
Bathsheba
  • 231,907
  • 34
  • 361
  • 483