int main(void)
{
int b[5] = {1,2,3,4,5,6,7,8,9,10};
int i;
for(i=0;i<9;i )
{
printf(" %d ",b[i]);
}
printf("\n address : %u",b);
return 0;
}
This is C program in which number of elements exceeds declared size. when i iterate through array it prints following output-
1 2 3 4 5 5 6422284 3854336 6422352
address : 6422288
compiler - gcc
i don't understand
- why 5 is printed twice
- why only 9 values are printed instead of 10
CodePudding user response:
Because the behavior of the program is not defined, and thus it will do whatever. Your expectation that “5 should not be printed twice” is just as speculative as any other expectation. Why do you think 5 should not be printed twice?!
Because the behavior of the program is not defined. Thus your expectation as to the behavior of the loop is just idle speculation.
You’ll see even more interesting things happen if you do a release (optimized) build. It may do nothing whatsoever, or crash, or do the same thing, or do something else out of the blue if the CPU’s IP gets corrupted or sent into the “blue”.
And by the way, your original program could too :)
CodePudding user response:
The C language specification contains the following constraint (C17 6.7.9/2):
No initializer shall attempt to provide a value for an object not contained within the entity being initialized.
Your initialization of b ...
int b[5] = {1,2,3,4,5,6,7,8,9,10};
... violates that constraint by including ten values in b's initializer list when b has only five elements, all scalars. A conforming compiler is obligated to emit a diagnostic about that, and if gcc does not do so by default then it probably can be made to do so by including the -pedantic flag. Generally speaking, with gcc you should use both -Wall and -pedantic at least until you know enough to make an informed decision of your own.
Technically, the behavior of your program is undefined as a result, but that's probably not the main issue in practice. I expect that gcc is just ignoring the excess initializer values. The main issue is that no matter how many initializer elements you provide, you have specified that b has exactly 5 elements, but you attempt to access elements at indices above 4. Those are out of bounds array accesses, and their behavior is undefined. You have no valid reason to expect any particular results of those, or that anything be printed at all.
In fact, the whole program has undefined behavior as a result, so it is not safe to assume that a program that performed all the same things except the out-of-bounds accesses would produce a subset of the output of the erroneous program.
With respect to your particular questions:
- why 5 is printed twice
The language specification does not say. The result of attempting to print b[5] is undefined.
- why only 9 values are printed instead of 10
Probably because of the iteration bounds, i=0;i<9;i . With those, and if the program otherwise conformed to the language specification, one would expect the loop body to be executed nine times (in particular, not when i has the value 9).
Note also that this ...
printf("\n address : %u",b);
... is wrong. The printf directive for printing pointers is %p, and, technically, it requires the argument to be a pointer to void (not, for example, a pointer to int). This would be fully correct:
printf("\n address : %p", (void *) b);
Addendum
If you want an array with exactly ten elements, then declare it so:
int b[10] /* initializer optional */;
If you want one whose size is chosen based on the number of elements in its initializer, then omit the explicit size:
int b[] = {1,2,3,4,5,6,7,8,9,10}; /* declares a 10-element array */
