2014-10-09 69 views
4

最近我一直在学习所有关于C语言,并且很困惑,使用何时使用char a []通过char p *,反之亦然?

char a[]; 

char *p; 

,当涉及到字符串操作。例如,我可以像这样的字符串分配给他们两个:

char a[] = "Hello World!"; 
char *p = "Hello World!"; 

,并查看/访问他们都喜欢:

printf("%s\n", a); 
printf("%s\n", p); 

和操纵他们都喜欢:

printf("%c\n", &a[6]); 
printf("%c\n", &p[6]); 

所以,我错过了什么?

+3

首先,使编译器警告 – 2014-10-09 13:33:45

+0

使用无论你想...只是语法糖en.wikipedia.org/wiki/Syntactic_sugar – zambotn 2014-10-09 13:34:11

+0

你错过了最重要的一点是在内存释放,多久你希望你的对象a住在你的节目中。 – Martin 2014-10-09 13:34:33

回答

9
char a[] = "Hello World!"; 

这种分配修改阵列只是大足以容纳字符串字面量(包括终止NUL字符)。然后它用字符串文字的内容初始化数组。如果它是一个局部变量,那么这意味着它在运行时会执行memcpy,每次创建局部变量时都会如此。

当您需要修改字符串时使用此选项,但不需要将其设置得更大。

此外,如果您有char *ap = a;,那么当a超出范围时ap将成为悬挂指针。或者,同样的事情,当a对于那个函数是局部的时候,你不能做return a;,因为返回值将悬挂指针到现在被销毁的那个函数的局部变量。

请注意,恰好使用这一点很少见。通常情况下,你不需要一个数组与字符串文字的内容。这是更为常见的有类似:

char buf[100]; // contents are undefined 
snprintf(buf, sizeof buf, "%s/%s.%d", pathString, nameString, counter); 

char *p = "Hello World!"; 

这定义指针,并初始化它指向字符串文字。需要注意的是字符串字面量(正常)不可写入的,所以你真的应该这个:

const char *p = "Hello World!"; 

使用此当你需要指向不可修改的字符串。

与上面a,如果你有const char *p2 = p;或做return p;,这些都很好,因为指针指向字符串中程序的常量数据的文字,有效期为程序的整个执行。


字符串文字本身的文字withing双引号,构成该字符串的实际字节,在编译时创建并通常被放置与该应用程序内的其他常量数据。然后在代码中字符串文字具体指这个常量数据blob的地址。

+2

一个澄清可能会有所帮助(或者可能会造成混淆)。无论哪种情况,编译器都会创建一个字符串文字并将其添加到可执行文件中。在数组的情况下,数组在运行时初始化(例如,您引用的'memcpy'在运行时发生,而字符串的创建则在编译时发生。)指针也在运行时初始化,但是初始化不会复制字符串 - 只是它的地址。 – 2014-10-09 13:38:31

+0

@WilliamPursell根据你的建议编辑了一下 – hyde 2014-10-09 13:58:28

+0

因此,如果我想将它与PHP(比较熟悉)进行比较,那我认为'''char * p;''类似于PHP常量和'''char a [];'''是一个普通的PHP变量? – 2014-10-09 15:54:48

2

char *字符串是只读的。字符串可以是char[],但不能修改。

char *str = "hello"; str[0] = 't'; // This is an illegal operation

char str[] = "hello"; str[0] = 't'; // Legal, string becomes tello

+2

“'char *'字符串是只读的”只有当你设置它们等于一个字符串文字(正如他在例子中所做的那样)。否则它们是完全可写的。 – wolfPack88 2014-10-09 13:38:29

+1

char *'从不是只读的,因为它不是'const char const *',但可以指向'const char',它当然是只读的。一如既往:指定存储类别使得全部清除 – 2014-10-09 14:13:27

相关问题