Reputation: 509
I have the following code:
#include <stdio.h>
int main(void) {
char list[3][7] = { "One", "Two", "Three"} ;
char item[7]; // originally I had posted "char item[3];" by mistake
int i;
for( i=0; i<2; i++ ) {
sprintf(item, "%-7s", list[i]);
printf( "%d %s", i, item );
}
printf("\n\r");
for( i=0; i<2; i++ ) {
sprintf(item, "%-7s", list[i]);
printf( "%d %s", i, item );
}
printf("\n\r");
return 0;
}
I expect the following output
0 One 1 Two
0 One 1 Two
However, instead I get:
0 One 1 Two
0 1 Two
Note the missing text "One" the second time it prints.
Can someone explain what's happening here?
Thanks!
Upvotes: 0
Views: 287
Reputation: 72226
With item
declared as:
char item[7];
the code exposes undefined behaviour because sprintf(item, "%-7s")
attempts to write at least 8 characters into item
.
The documentation of sprintf()
explains (the emphasis is mine):
Writes the results to a character string buffer. The behavior is undefined if the string to be written (plus the terminating null character) exceeds the size of the array pointed to by buffer.
-7
in the format string "%-7s"
is interpreted as:
(optional) integer value or
*
that specifies minimum field width. The result is padded with space characters (by default), if required, on the left when right-justified, or on the right if left-justified. In the case when*
is used, the width is specified by an additional argument of typeint
. If the value of the argument is negative, it results with the-
flag specified and positive field width. (Note: This is the minimum width: The value is never truncated.)
In order to avoid the undefined behaviour, the size of item
must be at least 8
but keep in mind that if the string to format is longer than 7
characters it is not truncated, the result becomes longer than 8
characters and it overflows item
again.
The calls to sprintf(item, "%-7s", list[i]);
in the first loop write 8 characters in a buffer of 7 characters. The extra character (which is \0
) incidentally happens to overwrite the first character of list[0]
changing it into an empty string. This is just one random behaviour, compiling the code with a different compiler or different compiling options could produce a different behaviour.
Upvotes: 1
Reputation: 14800
When you do the sprintf(item, "%-7s", list[i]);
you are, essentially, copying the string from list[i]
into your char array item
.
So list[2]
-> "three" is 5 chars plus the nul terminator, but item
is only 3 chars long -- you are overflowing item
and writing over some other memory, which could very well be part of list
.
Change item to be char item[7]
so it matches the length of 7 declared in your 2nd dimension in list[3][7]
. When I did that I got your expected output.
(I used https://repl.it/languages/C to test)
Upvotes: 1