C doesn't bounds check arrays. A C compiler is perfectly capable of producing the same machine code as an assembler when given a loop that writes bytes to an array and then keeps writing beyond the space allocated for the array.
Missingno wasn't the result of an array overrun, it was due to data in a set of registers (which had temporarily been used to store a string) being arbitrarily reinterpreted as structured data governing which pokemon were allowed to be encountered. It more closely resembles a compiler miscompilation than a typical logic bug that you'd encounter in a C program. An idiomatic C implementation of Pokemon Red/Blue (ignoring hardware limitations, which is of course why it was written in assembly in the first place) would have used a static array to hold the per-area pokemon encounter table, and would have used a global variable to hold the index into this array representing the player's currently-loaded encounter zone; at no point would the static encounter array have been overwritten by a string temporary (which, in our C implementation, is just a function local variable on the stack), and at no point would the global location index be overwritten with garbage, because just like in the original game it only gets updated when we load a zone where wild pokemon can be encountered (which means that surfing on the side of Cinnabar Island would result in encounters drawing from whatever encounter zone we had most recently visited).
Missingno wasn't the result of an array overrun, it was due to data in a set of registers (which had temporarily been used to store a string) being arbitrarily reinterpreted as structured data governing which pokemon were allowed to be encountered. It more closely resembles a compiler miscompilation than a typical logic bug that you'd encounter in a C program. An idiomatic C implementation of Pokemon Red/Blue (ignoring hardware limitations, which is of course why it was written in assembly in the first place) would have used a static array to hold the per-area pokemon encounter table, and would have used a global variable to hold the index into this array representing the player's currently-loaded encounter zone; at no point would the static encounter array have been overwritten by a string temporary (which, in our C implementation, is just a function local variable on the stack), and at no point would the global location index be overwritten with garbage, because just like in the original game it only gets updated when we load a zone where wild pokemon can be encountered (which means that surfing on the side of Cinnabar Island would result in encounters drawing from whatever encounter zone we had most recently visited).