Another interesting program from Andrew Koenig's C traps and pitfalls (I'm assuming a 32-bit, little-endian machine):
#include<stdio>
()
main{
int i;
char c;
for(i=0; i<5; i++)
{
("%d", &c);
scanf("%d ", i);
printf}
("\n");
printf}
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
("%d", &c); scanf
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.