在C语言中,可以在这样的声明中使用字符串字面值:

char s[] = "hello";

或者像这样:

char *s = "hello";

那么有什么不同呢?我想知道在编译和运行时,在存储持续时间方面实际发生了什么。


当前回答

举个例子来说明区别:

printf("hello" + 2); //llo
char a[] = "hello" + 2; //error

在第一种情况下,指针算术是有效的(传递给函数的数组衰减为指针)。

其他回答

char *s1 = "Hello world"; // Points to fixed character string which is not allowed to modify
char s2[] = "Hello world"; // As good as fixed array of characters in string so allowed to modify

// s1[0] = 'J'; // Illegal
s2[0] = 'J'; // Legal

在下列情况下:

char *x = "fred";

X是左值,它可以被赋值给。但在这种情况下:

char x[] = "fred";

X不是一个左值,它是一个右值——你不能给它赋值。

补充一点:它们的大小也会有不同的值。

printf("sizeof s[] = %zu\n", sizeof(s));  //6
printf("sizeof *s  = %zu\n", sizeof(s));  //4 or 8

如上所述,对于数组'\0'将被分配为最后一个元素。

不同之处在于

char *s = "Hello world";

将“Hello world”放置在内存的只读部分,并将s作为指向它的指针,使得对该内存的任何写入操作都是非法的。

虽然做的事情:

char s[] = "Hello world";

将字面值字符串放在只读内存中,并将字符串复制到堆栈上新分配的内存中。从而使

s[0] = 'J';

合法的。

char s[] = "Hello world";

这里,s是一个字符数组,如果我们愿意,它可以被覆盖。

char *s = "hello";

字符串字面值用于在内存中的某个地方创建这些字符块。我们可以通过改变它所指向的对象来重新赋值,但只要它指向一个字符串字面值,它所指向的字符块就不能被改变。