The question is not what the array does or doesn't contain, or what the compiler "knows" about the array size. The question is simply: how will we use the array once it's created, and in particular, how will we remember (how will the code we write and use know) how big the array is?
Although the compiler always knows, as it compiles the code, exactly how big each array is, that's a compile-time thing, not a run-time thing. There's no mechanism provided by the language that will tell us, at run time, how big an arbitrary array is. So it's up to us (so to speak) to figure it out.
And that's where null termination comes in. It's a convention in C (but a very important one!) that when you have an array of type char
, and when you're using that array as a "string', that the string must always be terminated by \0
. Every C function that deals with strings -- the predefined ones in the standard C library, along with any string-manipulating functions we might write -- every function depends on this convention. If you have an array of char
that's not null-terminated, and if you hand it to a string-processing function, the function will sail right off the end when it tries to figure out how big the string is, with variously undefined results.
By contrast to using a "sentinel value" like \0
to terminate an array, the other principal way to keep track of an array's size is with a separate "count" variable off to the side. That's how we'd probably keep track of your array v1
, either by using
int v1size = 3;
or maybe
int v1size = sizeof(v1) / sizeof(v1[0]);
How does c "know" when v1 ends, but it needs the '\0' in the character array to know when that ends?
The compiler is fully aware of how big each array is. (It's the compiler that adds the \0
to v2
, so it has to know!) The real question is, how does printf
know?
what would happen if... it was written as char v3[] = {'h', 'e', 'l', 'l', 'o'}
(other than getting out-of-bounds when I use a for-loop to detect the end of it).
Nothing would happen, except that you (and printf
, and strlen
, and strcpy
, and everybody else) would get get out-of-bounds errors (or the equivalent) when they tried to detect the end of it.
See also What's the rationale for null terminated strings?.