我下面初始化了三个变量:
char c1[] = "Hello";
char c2[] = { 'H', 'e', 'l', 'l', 'o', '\0'};
char* c3 = "Hello";
我知道c1和c2是相同的,它们都是字符串,因为它们以\0结尾。然而,c3与c1和c2不同。这是因为c3没有以\0结尾吗?这是否意味着c3不是一个字符串?如果c3不是一个字符串,那么为什么
printf("%s", c3);
不会报错呢?谢谢!编辑:c1和c2可以被修改,但c3不能,有原因吗?
就 C 语言而言,c3
和其他变量最重要的区别在于你不能尝试使用 c3
修改底层字符。我通常会这样思考:
char *xyz = "xyz";
会在栈上创建一个可修改的指针,并将其指向不可修改的字符序列{'x','y','z','\0'}
。另一方面,
char xyz[] = "xyz";
将创建一个可以修改的数组,该数组位于堆栈上,足够大,以容纳字符序列 {'x','y','z','\0'},然后将该字符序列复制到其中。数组内容将是可修改的。请记住,标准对堆栈没有任何规定,但通常是这样完成的。毕竟,这只是一个内存辅助工具。c1
和c2
也可以通过引用传递,这种情况下它们仍然不会衰变为指针。这取决于函数接收的方式。 - iammilindc3
”。更准确的说法难道不是“您可以修改指针c3
,但不能修改它所指向的字符串”吗? - ypercubeᵀᴹ第一点,
char* c3 = "Hello"; // may be valid C, but bad C++!
这是一种容易出错的风格,所以不要使用它。相反,请使用
const char* c3 = "Hello";
这是一段有效的代码。指针c3
指向存储"Hello"
字符串的位置的地址。但是,您不能修改*c3
(即c3
的内容),就像之前的情况一样(如果这样做,它是未定义的行为)。
c3
可以 被修改。c3
指向的字符串不安全,不能被修改。 - ypercubeᵀᴹgets
,它在c99中被弃用并在c1x中被移除。 - paxdiablochar*p = "foobar";
是允许的还是禁止的? - fredoverflowc3
是指向字符串的指针,这就是printf("%s", ...)
所期望的参数。
之所以printf("%s", c1)
或printf("%s", c2)
也可以工作,是因为在C语言中,数组很容易在表达式中“腐烂”成指针。事实上,在表达式中,数组名不会被“腐烂”成指针的唯一情况是它作为sizeof
运算符或&
(取地址)运算符的操作数时。
这导致了一个常见的混淆,即指针和数组在C语言中是等价的,这是不正确的。只是在C语言中,几乎可以在任何指针可用的地方使用数组。唯一的例外是它们不能被赋值,除非它们被下标引用(这会将其视为指针的表达式)。
请注意,最后一个字符串还有一个区别-由于它是字符串字面量,所以它不能被修改(如果尝试修改它,其结果是未定义的)。
c1
和c2
分配6个字节的内存,并在其中存储以空字符结尾的字符串。
然而,c3
在程序内存中分配了(同样以空字符结尾的)字符串,并创建一个指向它的指针,即该字符串与其他指令一起存储,而不是在堆栈(或堆?请有经验者纠正我)上,因此编辑它是不安全的。
"string"
可以有两种含义,取决于它所使用的上下文。它可以表示可执行文件中的 ro
段中的字符串(尽管我不认为标准明确说明了这一点),使得 const char *foo = "bar"
这个语句将 foo
初始化为指向已加载的可执行文件内存中的位置。如果二进制 blob ("bar"
) 确实在 ro
段中,并且你执行类似于 foo[0] = 'x'
的操作,你将会得到一个 SIGSEGV
。char x[] = "Hello"
(或者 char x[6] = "Hello"
)时,你是将 "Hello"
作为数组初始化器(就像 int x[2] = { 1, 2 }
),而 x
只是一个在堆栈上分配的普通(可写)数组。在这种情况下,"Hello"
只是 {'H', 'e', 'l', 'l', 'o', '\0' }
的简写。
"bar"
和"Hello"
都是以空字符结尾的。
c3
没有以 NUL 或 NULL 结尾。它是一个指向以 NUL 结尾的字符串的指针。
NULL
,并用于表示空指针常量。 - Michael Burr0
吗? - Tamer ShlashNULL
的用途,只是当谈论字符串终止时,它可能不是最好的术语(尽管实际上我认为它并不那么令人困惑,我自己经常使用它)。在C中,它通常被定义为类似于((void*) 0)
,而在C++中则简单地为0
。 - Michael Burr这是一个字符串它指向一个字符串,但是存在风险。
这是一个指向具有不同终止符的字符串的指针。
C3是指向字符串第一个单元格的指针。 C1、C2只是普通数组,没有被任何人指向。
c3
指向的 "Hello" 没有以\0
结尾? - Chris Eberle