char c[] = "Hello world!";
是分配一个局部数组。
char *c = "Hello world!";
是分配一个全局数组。
局部数组是局部变量,它对应的是内存中的栈。全局数组是全局变量,它对应的是内存中的全局区域。字符串常量保存在只读的数据段,而不是像全局变量那样保存在普通数据段(静态存储区),如:
char *c = "Hello world!";
*c = 't'; // 错误
c 占用一个存储区域,但是局部区的数据是可以修改的:
char c[] = "Hello world!";
c[0] = 't'; // 正确
这里 c 不占存储空间。
但是如果遇到先声明后赋值的情况:
char* sp, s[10];
sp = "Hello"; //正确
s = "Hello"; //错误
因为,数组名代表被分配的内存的首地址,是一个地址常量,是右值;而指针作为变量,却是一个左值。
增例(2019.08.13):
const char str1[] = "abc";
const char str2[] = "abc";
const char *p1 = "abc";
const char *p2 = "abc";
printf("%d %d %d %d\n", str1, str2, p1, p2);
结果:前面两个输出的数不同,后面两个相同
前两个是字符数组(如果不是全局),定义在栈上,明显地址不同
字符串常量定义在静态区,仅有一份拷贝,所以后面两个指针指向的地址相同