It is very easy for users to make grave mistakes, and the CRT will have no way of detecting them. If you misuse strncpy(), and omit copying the null-terminator, then trying to use strlen() later on will invoke undefined behavior, and likely crash. Additionally, for reasons mentioned above, anything involving knowing the string's length is a nightmare. Unless you pass the length yourself, calculating the length all of the time is unacceptable, because it has to loop over all of the characters to find the end. Using strcat() repeatedly means repeatedly finding the length of the destination string, then writing characters to the end of it. There's no way around that, unless you keep track of the length of the destination string after the end of each operation (which might require getting the length of the source string before each operation. D'oh!) Also, don't forget, if you are using strncat(), to make sure that there is a null-terminator. Rookie mistake.
You also don't have the luxuries of a higher-level string object: things like resizing the string whenever you please, iterating through characters starting from the _end_ of the string, finding the character in the middle of the string, etc. Since you could have gotten that string though any means, if it is determined that you don't have enough space in the string to store more characters, you might not have enough information to know whether the string was allocated with malloc(), on the stack, part of a memory-mapped file, or even garbage data. An std::basic_string has the ability to resize itself with its copy of its allocator class instance. A function that handles C-strings either must refuse to resize strings, or blindly trust that the caller has provided enough space for characters in the memory block. Worrying about this leads directly to using strncpy() and strncat(), which have a case where a null-terminator isn't appended, for historical reasons!
In closing, yes, it has all of the shortcomings of an array, and it lures the inexperienced (and sometimes the experienced, too) into somewhat of a false sense of security, by hiding how fragile a C-string is, causing them to handle them wrong and then the fun begins.