在C语言中,可以在这样的声明中使用字符串字面值:
char s[] = "hello";
或者像这样:
char *s = "hello";
那么有什么不同呢?我想知道在编译和运行时,在存储持续时间方面实际发生了什么。
在C语言中,可以在这样的声明中使用字符串字面值:
char s[] = "hello";
或者像这样:
char *s = "hello";
那么有什么不同呢?我想知道在编译和运行时,在存储持续时间方面实际发生了什么。
当前回答
补充一点:它们的大小也会有不同的值。
printf("sizeof s[] = %zu\n", sizeof(s)); //6
printf("sizeof *s = %zu\n", sizeof(s)); //4 or 8
如上所述,对于数组'\0'将被分配为最后一个元素。
其他回答
补充一点:它们的大小也会有不同的值。
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';
合法的。
首先,在函数参数中,它们是完全等价的:
void foo(char *x);
void foo(char x[]); // exactly the same in all respects
在其他上下文中,char *分配一个指针,而char[]分配一个数组。你会问,在前一种情况下,弦在哪里?编译器秘密地分配一个静态匿名数组来保存字符串字面值。所以:
char *x = "Foo";
// is approximately equivalent to:
static const char __secret_anonymous_array[] = "Foo";
char *x = (char *) __secret_anonymous_array;
注意,你不能试图通过这个指针修改这个匿名数组的内容;效果是未定义的(通常意味着崩溃):
x[1] = 'O'; // BAD. DON'T DO THIS.
使用数组语法直接将其分配到新的内存中。因此修改是安全的:
char x[] = "Foo";
x[1] = 'O'; // No problem.
然而,数组只在其包含范围内存在,所以如果在函数中这样做,不要返回或泄漏指向该数组的指针——而是使用strdup()或类似的方法进行复制。如果数组是在全局范围内分配的,当然没有问题。
在下列情况下:
char *x = "fred";
X是左值,它可以被赋值给。但在这种情况下:
char x[] = "fred";
X不是一个左值,它是一个右值——你不能给它赋值。
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