The first example creates an array with three elements. It's equivalent to
char string[3] = { 'A', 'B', 'C' };
The second example uses the string literal "ABC"
which is an array of four characters, and then make the pointer pString
point to the first character. It's equivalent to
char compiler_internal_string[4] = { 'A', 'B', 'C', '\0' };
char *pString = &compiler_internal_string[0];
Note how the two arrays are different: Your doesn't have the terminating null-character that all string-related functions look for to know when the string ends.
Since your array is missing the terminator, all string function will go out of bounds of the array, and that leads to undefined behavior.
Unless you want to make an array larger than the string it contains, for example to be able to append to it, then the simple solution is to just not provide the size:
char string[] = "ABC"; // Will create an array of four characters,
// and include the terminator
On another note, literal strings are not modifiable, they are in effect read-only. Therefore it's recommended to use const char *
pointers to point to string literals, to make the chances of accidental modifications smaller.