So. I am teaching programming 1 to some college level pupils at the moment. And i specifically told them to go out and look online for references, specifically on the datastructure parts i am covering at the moment. Today one student emailed me with a link to tutorialspoint.com and asked about this piece of code he pulled from there:
#include <stdio.h>
main() {
int LA[] = {1,3,5,7,8};
int item = 10, k = 3, n = 5;
int i = 0, j = n;
printf("The original array elements are :\n");
for(i = 0; i<n; i++) {
printf("LA[%d] = %d \n", i, LA[i]);
}
n = n + 1;
while( j >= k) {
LA[j+1] = LA[j];
j = j - 1;
}
LA[k] = item;
printf("The array elements after insertion :\n");
for(i = 0; i<n; i++) {
printf("LA[%d] = %d \n", i, LA[i]);
}
}
Now, without knowing exactly where it's from i don't know exactly how they described it, but obviously it is insertion into an array of value at index k, shuffling upwards from k.
Now what he asked about was that i have told my students that when doing something like:
int arr[] = {1,2,3,4};
the compiler will auto-count the size, by checking the supplied value list. This case means an array size of 4 elements. I have also told them that an array size is fixed when the array is first initialized, like:
int likethis[5];
int orthis[] = {1,2,3,4};
int orlikeso[MAX_ARR_SIZE];
Thus, to resize an array, dynamic memory management is needed, so that you would declare space for a new array (a part of the course they have yet to get to).
But the code from this tutorial site actually seems to do an auto-size by the compiler with the initializer list, then go about merrily resizing it in the loop, when shuffling.
So the final size of LA in their example would be 6 elements. Now, my student wants to know why this is valid. I have not tested this code myself, but apperantly it compiles on GCC according to my student. If so, how can that code be valid? Wouldn't this overwrite the boundaries of LA, when setting LA[5] in the shuffle loop?
Questions: Is it me who is an old geezer, and this is allowed in C since way back? Only in GCC? Seeing as i learned C in the 80s somewhere, i assume i might be wrong here, but to me it is writing past the assigned size of LA. Just wanted to check it on S.O.
But the code from this tutorial site actually seems to do an auto-size by the compiler with the initializer list, then go about merrily resizing it in the loop, when shuffling.
The code only appears to do that. In reality, the code causes undefined behavior as soon as it touches index 5 of a five-element array.
Now, my student wants to know why this is valid.
He should have started with a simpler "is this valid" question. The answer to it would be "no". The code will compile, and may even appear to work, but this code is invalid.
Unfortunately, there is no easy way to demonstrate it to students at the early stages of learning C, because reading memory profiler reports (say, valgrind) is an advanced skill. On the other hand, if the students have enough determination to learn how to run their code through a memory profiler, they are in for a very rewarding experience of having good confidence in their code.
Note: I think this is a great teaching moment, because it lets you teach the student an important point about undefined behavior in C, and also reinforce the rule "you shouldn't trust things just because you found them on the internet" applies to code as well.
By attempting to write past the last element of the array, the code invokes undefined behavior, which means it may crash outright, silently corrupt data, or appear to run without any problems.
There may be some padding or scratch space that the extra element is being written to, which is why it isn't crashing, but this code is not valid.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With