Apart from the problem that a string literal in C++ is const:
What you see is the normal way arrays in C, and by association in C++, are passed and handled. In most cases an array "decays" to a pointer to its first element when it is passed or used in an expression. So yes, you are right: ch is a pointer to the first char. And all C/C++ routines around char arrays, a.k.a. C strings, rely on the string being 0 terminated. Somewhere in the valid memory area starting at the adress given, a byte with the value zero must indicate that the string logically ends here. For example operator<< will stop copying characters from that memory to cout when it encounters a zero byte. Functions like strcat() just overwrite that zero byte and append a new one where the new, longer string now "ends".
The background is that C/C++ arrays do not carry any "ancillary information". There is not any data associated with them beyond the bare sequence of their elements in memory.
As an aside, for types that do not have "invalid" values (like 0 for a char) which could serve as an end marker, there is no way a function can find the end of an array passed to it, because the function gets only a pointer to the first element. All such functions need a second parameter indicating the array's length. This primitive array handling (which is, of course, extremely fast and trivially translatable in any machine code) is very different from languages with a safer and more abstract type system like Ada or C#, where an array carries information about its length.