In (2) the string exists only in one version, and you are manipulating it directly by its address.
In (1) there is the string somewhere in memory, and then you put this address in another location in memory and force yourself to read the address from the other location each time you need it. In effect, it adds a (useless) indirection.
EDIT:
As I say in the comments below and for another answer, there is no duplication in (2).
t.c:
char *p = "This is a test";
char s[] = "This is a test";
The command gcc -S t.c
produces the file:
.globl _p
.cstring
LC0:
.ascii "This is a test\0"
.data
.align 2
_p:
.long LC0
.globl _s
_s:
.ascii "This is a test\0"
.subsections_via_symbols
ts.c:
char s[] = "This is a test";
The command gcc -S ts.c
now produces the file:
.globl _s
.data
_s:
.ascii "This is a test\0"
.subsections_via_symbols