C字符串指针 vs. 数组

13

可能是重复问题:
char s[]和char *s在C中有什么区别?

为什么会是这样:

char *ptr = "Hello!"

与...不同:

char ptr[] = "Hello!"

具体来说,我不明白为什么可以使用 (*ptr)++ 来更改数组中 'H' 的值,但无法更改指针本身的值。

谢谢!

5个回答

42
可以(通常情况下)使用表达式(*ptr)++来改变指针ptr所指向的值,当ptr是指针而不是数组时(即ptr声明为char* ptr的情况)。

但是,在你的第一个例子中:

char *ptr = "Hello!"

ptr指向一个字面字符串,而字面字符串是不允许被修改的(它们实际上可能存储在不可写的内存区域中,例如ROM或标记为只读的内存页)。

在你的第二个例子中,

char ptr[] = "Hello!";

该数组被声明并初始化时,实际上会将字符串文字中的数据复制到已分配的数组内存中。该数组内存是可修改的,因此(*ptr)++有效。

注意:对于您的第二个声明,ptr标识符本身是一个数组标识符,而不是指针,并且不是“lvalue”,因此无法修改(即使在大多数情况下它容易转换为指针)。例如,表达式++ptr是无效的。我认为这就是其他一些回答试图说明的要点。


1
最后,有人回答了我的问题。如果我有注册账户,我会给您点赞的。非常感谢您,亲切的先生。 - John McGee
8
@John McGee:你发布问题就意味着你拥有一个“账户”,你有足够的声望来点赞,而且你总是可以将一个答案标记为“已采纳”。 - jamesdlin
我现在太懒了,但是在第一种情况下(*ptr)++真的会导致编译器错误吗?编译器需要分析指针自初始化以来是否发生了变化,不是吗? - MartinStettner
@Martin:通常不会导致编译时错误(如果您的编译器聪明并且能够检测到ptr指向文字常量,则可能会发出警告),但它经常会导致运行时错误。然而,在某些平台上,它可能看起来可以工作 - 但这是未定义的行为,并且应该在任何平台上视为错误。 - Michael Burr
1
@Michael:谢谢。更不用说常量字符串被共享(即重复使用)的情况,这种情况更为普遍,我认为... - MartinStettner
显示剩余2条评论

2
当指向字符串字面值时,不应将字符声明为可修改的,一些编译器会对此发出警告。
char *ptr = "Hello!"    /* WRONG, missing const! */

其他人指出的原因是字符串字面量可能存储在程序内存的不可变部分。

你需要做的正确“注释”是确保你有一个指向常量字符的指针:

const char *ptr = "Hello!"

现在你可以直接看到,你无法修改存储在指针中的文本。


0

数组会自动分配空间,但是它们不可重定位或调整大小,而指针则明确指向已分配的空间并可以被重新定位。

数组名称是只读的!


谢谢,但这并没有回答我的问题。我想知道为什么对于数组来说(*ptr)++会将'H'更改为'I',但对于另一种情况却不会。 - John McGee

0
如果你使用一个字符串文字"Hello!",该文字本身会成为一个由7个字符组成的数组,并存储在数据内存的某个位置。这块内存可能是只读的。
这个语句
char *ptr = "Hello!";

定义一个指向char的指针并将其初始化,通过将字面量(先前提到的7个字符的数组)开头的地址存储在其中。更改由ptr指向的内存内容是非法的。

该语句

char ptr[] = "Hello!";

定义了一个char数组(char ptr[7]),并通过从字面值复制字符到数组中进行初始化。该数组可以被修改。


0

在C语言中,字符串是字符数组。指针是一个变量,它包含另一个变量的内存地址。数组是一组有序的数据项。当你使用(*ptr)++时,指针会出现分段错误。

也许你正在将1添加到整个字符串(使用指针),而不是将1添加到变量的第一个字符(使用数组)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接