If in special cases the second method is always preferred, i.e. Do not type the size of the array explicitly. This avoids the error that you seemingly quietly created in your example.
To understand this, you must first understand what a string is. The null character is indicated by the character '\0' . A string is a sequence of zero or more non-zero char s ending with one null character. This last bit is very important. Take a look at the following code:
const char* my_string = "xyz"; size_t string_len = strlen( my_string );
A pointer is just a memory address. It does not contain any information about size or length. Then, how strlen() measure the length of my_string ? This, of course, is by measuring the number of non-zero characters from a line starting immediately before the terminating null character. You may have noticed that the terminating null character is implicit in the string literal. The above string literal creates an array in memory that looks like this:
_______ _______ _______ _______ | | | | | | 'x' | 'y' | 'z' | '\0' | |_______|_______|_______|_______| ^ | `my_string` is a pointer to this cell
The array itself has no name, but the compiler manages to assign its first element address as my_string value. So what happens to your first example?
char my_string[ 3 ] = "abc";
In the standard definition, a string literal is of type char[ N ] , where N is the length of the string plus one to count the null character (note that string literals are not declared const for historical reasons, but it is still undefined to change them). Thus, the above expression "abc" is of type char[ 4 ] . my_string , on the other hand (now it is an array, not a pointer, BTW) is of type char[ 3 ] . That is, you are installing a smaller array for a larger array, since 4 > 3 . The standard provides that in this exact situation, when the null character of a string literal does not fit into an array, it will be truncated. So my_string looks like this:
_______ _______ _______ | | | | | 'a' | 'b' | 'c' | |_______|_______|_______|
It looks fine, but ... wait. Where does the null character end? You chopped it off by explicitly declaring the size of the array! Now how should strlen() determine the length of a string? It will simply continue reading characters line by line until a null character is found by coincidence. This behavior is undefined. On the other hand, doing this:
const char[] my_string = "abc";
You do not risk doing this. The type my_string will be automatically my_string to const char[ 4 ] , and the null character will be saved.
tl; dr Do not forget about the terminating null character!