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

char s[] = "hello";

或者像这样:

char *s = "hello";

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


当前回答

char s[] = "hello";

声明s为一个char数组,其长度足以容纳初始化式(5 + 1个字符),并通过将给定字符串文字的成员复制到数组中来初始化数组。

char *s = "hello";

声明为指向一个或多个(在本例中是多个)字符的指针,并将其直接指向一个包含文字“hello”的固定(只读)位置。

其他回答

另外,考虑到对于只读目的,两者的使用是相同的,您可以通过使用[]或*(<var> + <index>)索引来访问一个char。 格式:

printf("%c", x[1]);     //Prints r

And:

printf("%c", *(x + 1)); //Prints r

很明显,如果你试图这么做

*(x + 1) = 'a';

你可能会得到一个分割错误,因为你试图访问只读内存。

首先,在函数参数中,它们是完全等价的:

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 * s = "hello"; 是一个坏主意,应该在非常狭窄的范围内使用。

这可能是指出“const正确性”是一件“好事”的好机会。无论何时何地,你可以使用“const”关键字来保护你的代码,不受“宽松”的调用者或程序员的影响,当指针开始发挥作用时,它们通常是最“宽松”的。

这就是用“const”修饰指针所能达到的效果。 (注意:必须从右向左阅读指针声明。) 以下是在使用指针时保护自己的3种不同方法:

const DBJ* p means "p points to a DBJ that is const" 

-也就是说,DBJ对象不能通过p改变。

DBJ* const p means "p is a const pointer to a DBJ" 

-也就是说,你可以通过p改变DBJ对象,但你不能改变指针p本身。

const DBJ* const p means "p is a const pointer to a const DBJ" 

-也就是说,你不能改变指针p本身,也不能通过p改变DBJ对象。

与尝试常量突变相关的错误在编译时被捕获。const没有运行时空间或速度损失。

(当然,假设你使用的是c++编译器?)

——日本

char s[] = "hello";

声明s为一个char数组,其长度足以容纳初始化式(5 + 1个字符),并通过将给定字符串文字的成员复制到数组中来初始化数组。

char *s = "hello";

声明为指向一个或多个(在本例中是多个)字符的指针,并将其直接指向一个包含文字“hello”的固定(只读)位置。

char *str = "Hello";

上面设置str指向“Hello”字面值,该字面值是硬编码在程序的二进制图像中,在内存中被标记为只读,这意味着这个String字面值的任何更改都是非法的,并且会抛出分割错误。

char str[] = "Hello";

将字符串复制到堆栈上新分配的内存中。因此,对它进行任何更改都是允许的和合法的。

means str[0] = 'M';

将str更改为“Mello”。

如欲了解更多详情,请浏览类似问题:

为什么我得到一个分割错误时写入一个字符串初始化“char *s”而不是“char s[]”?