Another example from C traps and pitfalls

Another example from Andrew K├Ânig's book..

From my old blog.

Another interesting program from Andrew Koenig's C traps and pitfalls (I'm assuming a 32-bit, little-endian machine):

    int i;
    char c;
    for(i=0; i<5; i++)
        scanf("%d", &c);
        printf("%d ", i);

Most of us would expect the output to be:

0 1 2 3 4

when we provide some input but it turns out that it might not be the case.

Notice the line

scanf("%d", &c);

where the %d format specifier is used instead of %c to store the value read as input into the variable c. This causes scanf() to think that the address provided is the address of an integer and writes data over sizeof(int) bytes thereby intruding upon the memory of some other variable which might very well be part of the area where i is stored.

So, initially,

i = 0
c = garbage (let's assume it's 0x61)

The variable i and c could (platform dependent) be in memory like this:

|  Value   |     0x00 |     0x00 |     0x00 |     0x00 |     0x61 |
|  Memory  | 0x45678F | 0x45678E | 0x45678D | 0x45678C | 0x45678B |
| Variable |                int i                      |  char c  |

The address of i is 0x45678C and that of c is 0x45678B.

The scanf() here can intrude upon the bytes at 0x45678C, 0x45678D and 0x45678E of i as the address 0x45678B is provided to scanf() and sizeof(int) is 4 (this value is platform dependent).

While reading into c if a value < 256 is entered, the lower bytes (in a little endian machine otherwise the higher bytes) of the 'integer' whose base address is the address of c will become zero.

The values that the least signicant byte of i will assume for different ranges of input are:

Input value range Value in LSB
[0, 255] 0
[256, 511] 1
[512, 767] 2
[768, 1023] 3
[1024, 1279] 4

The loop will go on as long as i < 5. That means as long as i < 4 at the end of each iteration, the loop will go on. ie, as long as the input is a number < 1024, the loop will go on.