This is not because of strcpy()
- it does the same thing in both cases: It copies characters in sequence from the source to corresponding positions at the destination location until the \0
at the end of the source string.
The reason you're getting a segmentation fault in the second case is that those string literals are now in a different segment of memory, which is read only (e.g. it could be together with the compiled program text). When strcpy()
tries to write characters in there, your process gets interrupted and the kernel tells you "You can't do that, you're violating the segmentation of memory" (hence a segmentation violation or fault).
In the first case, those read-only string literals still exist, but you're using them to initialize a local variable - the (two dimensional) array, which is located on the stack. The two-dimensional array is not an array of pointers, it is actually an array of characters, and C just "arranges" the accesses to that array so that you can use pairs of square brackets.
See:
here on StackOverflow, for more on these topics.