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

一、字符数组

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

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

[cpp] view plain copy    
  1. char str1[10]="Hello";
  2. char str2[]="World";
  3. char str3[]={'H','e','l','l','o'};

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

[cpp] view plain copy    
  1. char str4[10];
  2. str4={'H','e','l','l','o'};    // 错误
  3. str4="Hello";                  // 错误
  4. 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 plain copy    
  1. char *ptr="C++";
  2. char strArr[]="C++";
  3. char *ptr2=strArr;

使用cout<<ptr即可输出整个字符串,而使用cout<<*ptr则输出字符串的首字符。

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

三、区别

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

[cpp] view plain copy    
  1. char s[]="abc";
  2. char *ptr="abc";
  3. cout<<s<<endl;               // abc
  4. cout<<*s<<endl;              // a
  5. cout<<&s<<endl;              // 地址
  6. cout<<(s+1)<<endl;           // bc
  7. cout<<*(s+1)<<endl;          // b
  8. cout<<&s[1]<<endl<<endl;     // a
  9. cout<<ptr<<endl;             // abc
  10. cout<<*ptr<<endl;            // a
  11. cout<<&ptr<<endl;            // 地址
  12. cout<<(ptr+1)<<endl;         // bc
  13. cout<<*(ptr+1)<<endl;        // b
  14. cout<<&ptr[1]<<endl;         // a

这些代码应该能够说明char s[]和char *ptr之间的相似点了。它们都是指向字符串的指针。

下面说二者的不同之处。如下一段代码:

[cpp] view plain copy    
  1. char ss[]="C++";
  2. ss[0]='c';                  // 合法
  3. char *p="C++";
  4. 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 plain copy    
  1. char *strA()
  2. {
  3. char str[]="Hello";
  4. return str;
  5. }

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

将上述代码修改:

[cpp] view plain copy    
  1. char *strA()
  2. {
  3. char *str="Hello";
  4. return str;
  5. }

该函数能够正常运行,因为str指向的字符串字面值被保存在只读的数据段,是全局的,当函数调用完成后,str指向的地址未发生变化。

综上,可以看出使用char []较容易出错,可能出现不确定的结果。C++提供的string类相比之下,要安全的多了。

字符串数组 和 字符串指针 的区别相关推荐

  1. C语言—字符串与字符数组,字符串数组与字符串指针的区别

    字符串与字符数组 字符串一定是一个char的数组,但char的数组未必是字符串.--以字符'\0'结尾的char数组就是一个字符串,但如果char数组没有以'\0'结尾,那么就不是一个字符串,只是普通 ...

  2. C语言:字符串数组与字符串指针数组

    1,首先,不论是局部,静态还是全局数组都必须在定义的时候初始化,否则就得通过其他方式,eg 循环操作,字符串处理函数strcpy() 2,附以下代码: 主要完成将"I am from chi ...

  3. c语言字符数组给字符指针,C语言常见有关问题之字符串数组和字符指针数组有关问题...

    C语言常见问题之字符串数组和字符指针数组问题 通过如下的实例来讲解这个问题: #include int main(void) { char a[3][4] = {"123", &q ...

  4. char[]数组与char *指针的区别

    char[]数组与char *指针的区别 问题描述 虽然很久之前有看过关于char指针和char数组的区别,但是当时没有系统的整理,到现在频繁遇到,在string,char[], char *中迷失了 ...

  5. 神奇的判断数组名和指针的区别

    神奇的判断数组名和指针的区别 代码 代码 傻傻的区分不清楚数组名和指针的区别,下面的代码可以证明指针和数组名其实不是一个东西: // An highlighted block #include< ...

  6. 从编译器角度分析C语言中数组名和指针的区别

    从编译器角度分析C语言中数组名和指针的区别 数组名和指针是两个往往很容易让人们混淆的概念,很多人以为数组名就是一个指针,也有很多人知道数组名不同于指针但是仅知道数组名的值不能像指针一样改变. 例如你可 ...

  7. 如何在JavaScript中获取字符串数组的字符串?

    本文翻译自:How do you get a string to a character array in JavaScript? How do you get a string to a chara ...

  8. java字符串转字符串数组_Java字符串数组到字符串

    java字符串转字符串数组 Today we will look into how to convert Java String array to String. Sometimes we have ...

  9. java字符串转字符串数组_Java字符串数组

    java字符串转字符串数组 Java String array is used to hold fixed number of Strings. String array is very common ...

  10. golang 字符串拼接 字符串数组转字符串

    1.字符串拼接 一般对于少量的字符串拼接可以直接用+来连接,不过最好的方法还是Builder. 用buffer.Builder,官方建议用这个. package mainimport ("f ...

最新文章

  1. CodeGen处理Synergy方法目录
  2. IT项目需求分析的注意事项
  3. 六、最通俗易懂的JavaScript进阶教程(二)
  4. 23 年后来自生命溪流的回响 — FF7 Remake 音乐深度解析
  5. Mac OS使用技巧之二:修改变量Path解决android: command not found
  6. 转 C#对多个集合和数组的操作(合并,去重,判断)
  7. C语言小白适合入门的项目——扫雷
  8. linux系统c++编译连接过程,动态库与静态库
  9. android listview动态添加viewpager,向 ViewPager 中添加 包含 ListView 的 Fragment
  10. 2021年高考文科成绩 查询,预计2021年高考文科分数线
  11. Java并发编程原理与实战十一:锁重入自旋锁死锁
  12. lj245a引脚功能图_零基础入门单片机(2)学会控制IO引脚你就入门啦
  13. pands 画图 调整大小_两个精品案例解释机械设计的步骤,有思路,再着手画图...
  14. CAJViewer 无法获取document路径问题--360卫士C盘搬家
  15. CorelDRAWX4的VBA插件开发(十五)选择分辨率一键导出多张图片到桌面
  16. PS2汉化2 - 自制程序的运行与调试
  17. PDF怎么转换成图片?来看这两种好用的方法
  18. VC++界面编程之--实现工具栏自定义皮肤
  19. python格式化输出(二)--字符串的格式化输出
  20. 计算机考研跨审计好跨嘛,跨专业如何考研

热门文章

  1. react系列知识---11组件间抽象
  2. 第 18 章 Django 入门
  3. [转]一张图理解prototype、proto和constructor的三角关系
  4. ASP.NET服务器控件数据绑定总结
  5. 130108还原临时表空间
  6. 在 Red HatAS4下添加网卡驱动!!
  7. HashMap之三问为什么及性能问题
  8. Linux安装ipvsadm工具查看ipvs
  9. 【网址收藏】VMware虚拟机安装Windows7
  10. kafka topic常用命令