char str[]与char *str的区别

      在C语言中,对字符串的操作主要有两种方式,一是使用字符数组,char str[];二是使用字符指针。那么二者有什么区别呢?下面将分述二者的使用,最后进行比较。






一、字符数组


        使用char str[]定义一个字符数组str,中括号内可以写上数字表示数组大小,也可以不写。如果不写数字,则必须为字符数组提供初始值,以便编译器进行内存分配。


可以使用字符串字面值(string literal)来初始化字符数组,也可使用字符字面值(character literal)初始化,如:




[cpp] view plaincopyprint?
char str1[10]="Hello";  
char str2[]="World";  
char str3[]={'H','e','l','l','o'};  


只能对字符数组元素的赋值,而不能用赋值语句对整个数组赋值,如:


[cpp] view plaincopyprint?
char str4[10];  
str4={'H','e','l','l','o'};    // 错误  
str4="Hello";                  // 错误  
str4[0]='H';str4[1]='e';str4[2]='l';str4[3]='l';str4[4]='o';   // 正确  


可以使用循环将字符数组中的字符一个一个输出,也可以使用cout<<str1直接输出整个数组。
需要注意的是,上述代码中str1和str2是C风格字符串,而str3不是。C风格字符串,是指以\0结尾的字符数组。C++为了兼容C,而保留了C中字符串的使用方法。


str1和str2使用字符串字面值进行初始化,字符串字面值使用\0表示字符串结束。因此str2长度为6,需要将\0计算在内。使用strlen函数,计算的是字符串的实际长度,不包含\0。


而str3则不一样,它没有\0作为结束标志,因而不是C风格字符串,使用cout<<str3可能会出现意想不到的结果。






二、字符指针


可以使用char *str指向一个字符串。如:




[cpp] view plaincopyprint?
char *ptr="C++";  
char strArr[]="C++";  
char *ptr2=strArr;  


使用cout<<ptr即可输出整个字符串,而使用cout<<*ptr则输出字符串的首字符。
字符指针也可指向C风格字符串,如ptr就是指向的C风格字符串。如果让ptr指向上节中的str3,输出ptr会出现同样的意想不到的结果。毕竟数组名其实就是一种指针。






三、区别


前面简单介绍了一下两种操作字符串的方法,这部分进行比较,是本文的重点。如下代码:




[cpp] view plaincopyprint?
char s[]="abc";  
char *ptr="abc";  
cout<<s<<endl;               // abc  
cout<<*s<<endl;              // a  
cout<<&s<<endl;              // 地址  
cout<<(s+1)<<endl;           // bc  
cout<<*(s+1)<<endl;          // b  
cout<<&s[1]<<endl<<endl;     // a  
cout<<ptr<<endl;             // abc  
cout<<*ptr<<endl;            // a  
cout<<&ptr<<endl;            // 地址  
cout<<(ptr+1)<<endl;         // bc  
cout<<*(ptr+1)<<endl;        // b  
cout<<&ptr[1]<<endl;         // a  


这些代码应该能够说明char s[]和char *ptr之间的相似点了。它们都是指向字符串的指针。
下面说二者的不同之处。如下一段代码:




[cpp] view plaincopyprint?
char ss[]="C++";  
ss[0]='c';                  // 合法  
char *p="C++";  
p[0]='c';                   // 合法但不正确  


该段代码在VS2010下编译可以通过,但是运行时程序会停止工作,为什么呢?原因在于p[0]='c'这一语句。该语句试图修改p指向的字符串的首个字符,出现了错误。
原因在于两种方式对字符数组操作的机制不同。使用char *p="C++"语句后,编译器在内存的文字常量区分配一块内存,保存”C++“这一字符串字面值,然后在栈上分配内存保存p,p的内容为"C++"的地址。p[0]='c'试图修改常量”C++“,程序当然就会崩溃了。而char ss[]="C++"语句,定义了一个数组,编译器为其在栈上分配了内存空间,因而可以进行修改操作。


因此,可以总结如下:


(1)char ss[]定义了一个数组,ss可认为是一个常指针,ss不可改变,但ss指向的内容可以发生改变。


(2)char *p定义了一个可变指针,p可以指向其它对象。但对于char *p=”abc“这样的情况,p指向的是常量,故内容不能改变。






如下代码进一步说明char ss[]和char *p的区别:




[cpp] view plaincopyprint?
char *strA()  
{  
    char str[]="Hello";  
    return str;  
}  


调用该函数,不一定能够得到正确的结果。因为str定义了一个局部数据,是局部变量,存在于函数strA中的栈帧中。当函数调用完成后,栈帧恢复到函数strA调用前的状态,临时空间被重置,为函数分配的栈空间被收回,str所指向的地址也就不存在了。
将上述代码修改:




[cpp] view plaincopyprint?
char *strA()  
{  
    char *str="Hello";  
    return str;  
}  


该函数能够正常运行,因为str指向的字符串字面值被保存在只读的数据段,是全局的,当函数调用完成后,str指向的地址未发生变化。
综上,可以看出使用char []较容易出错,可能出现不确定的结果。C++提供的string类相比之下,要安全的多了。














参考自:http://blog.csdn.net/yahohi/article/details/7427724




——The End—— 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值