There are actually two problems here. One is the absence of bounds checking. The other, which is related but technically orthogonal, is the hole in the type system: an array is not an object. It's been true since Unix v7 that you can pass or return a struct by value, but you can't pass an array by value unless you wrap it in a struct.
The type system also makes no distinction between a pointer to a single object and a pointer into an array of objects. I've worked on static analysis tools that try to find potential buffer overflows, and this turns out to be a surprisingly big problem. One has to do a global dataflow analysis just to discover which pointer variables could ever point at array elements.