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

一、字符数组

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

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

[cpp] view plain copy print?

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

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

[cpp] view plain copy print?

  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 print?

  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 print?

  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 print?

  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 print?

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

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

将上述代码修改:

[cpp] view plain copy print?

  1. char *strA()
  2. {
  3. char *str="Hello";
  4. return str;
  5. }

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

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

char a[](字符串数组)和char *a(字符串指针)区别相关推荐

  1. c+字符串数组_了解C ++字符串数组

    c+字符串数组 Hey, Folks! So, as programmers, we often deal with Arrays of all data types. We'll cover C++ ...

  2. 使用C#删除一个字符串数组中的空字符串

    C#中要如何才能删除一个字符串数组中的空字符串呢?随着微软对C#不断发展和更新,C#中对于数组操作的方式也变得越来越多样化.以往要实现过滤数组中的空字符串,都是需要实行循环的方式来排除和过滤.C#3. ...

  3. java字符串数组转json_java中字符串String格式转化成json格式

    java字符串数组转json_java中字符串String格式转化成json格式 String s= Connection.deleteHost("10310");System.o ...

  4. c语言字符串数组分配没错,【字符串数组面试题】面试问题:C语言基础小结… - 看准网...

    26. 位段:指定结构体中成员变量所占的位数(以位的形式紧凑存储) unsigned char/int aaa:1 这里只能是unsigned char/int类型 27. 指针数组:int *p[1 ...

  5. C++接收字符串数组_C语言处理字符串的7个函数

    C库提供了多个处理字符串的函数,ANSI-C把这些函数的原型放在string.h头文件中.其中最常用的函数有strlen().strcat().strcmp().strncmp().strcpy()和 ...

  6. java生成字符串数组_Java 生成随机字符串数组的实例详解

    Java 生成随机字符串数组的实例详解 利用Collections.sort()方法对泛型为String的List 进行排序.具体要求: 1.创建完List之后,往其中添加十条随机字符串 2.每条字符 ...

  7. php字符串数组访问,php – 按字符串键x访问数组,其中x是“123”

    我们有一个数组,其中键是字符串,但这些字符串有时只是数字(例如"123").当尝试通过键"123"访问数组时,我们得到一个未定义的索引通知.当仅通过整数123访 ...

  8. java字符连接字符串数组_Java中连接字符串的最佳方法

    java字符连接字符串数组 最近有人问我这个问题–在Java中使用+运算符连接字符串是否对性能不利? 这让我开始思考Java中连接字符串的不同方法,以及它们如何相互对抗. 这些是我要研究的方法: 使用 ...

  9. c#解析json字符串数组_C#解析JSON字符串总结

    JSON文件读取到内存中就是字符串,.NET操作JSON就是生成与解析JSON字符串. 操作JSON通常有以下几种方式: 1. 原始方式:按照JSON字符串自己来解析. 2. 通用方式[★★★★★]: ...

最新文章

  1. 征途单机版场景服务器端口被占用,模拟城市5解决端口被占用的方法
  2. ML之xgboost:绘制xgboost的二叉树graphviz的两种方法代码实现
  3. 如何深入浅出的理解数据仓库建模?
  4. document.body.scrollTop的值为零问题
  5. linux php不能写文件内容,php 在linux系统下写出文件问题
  6. Go语言中时间轮的实现
  7. springboot+druid+mybatis+mysql+多数据源
  8. 梳理一下自己的技术关注面[转]
  9. tensorflow中协调器 tf.train.Coordinator 和入队线程启动器 tf.train.start_queue_runners
  10. Leetcode 刷题笔记(二十) ——回溯算法篇之分割、子集、全排列问题
  11. 【运维安全】Apache 服务器存在高危提权漏洞,请升级至最新版本 2.4.39
  12. paip.指针 引用 c++ java的使用总结.
  13. java写培根披萨和海鲜披萨_java子类继承父类实例-披萨的选择实现代码
  14. php+mysql 图书管理系统源码AfireHong
  15. 支付宝支付时提示“长时间没操作,请重新发起请求”的错误处理
  16. 浏览器渲染原理及性能优化
  17. excel合并两列内容_技巧不求人169期 Excel打印最常用的8大技巧 Excel合并多表数据...
  18. 关于Landsat所有知识都在这里
  19. 量化投资 --- 技术篇 (1) CAPM模型
  20. n-gram代码实现源码

热门文章

  1. PtInRect和WindowFromPoint判断鼠标是否停留在指定窗口上
  2. OOo:重新设计,全面翻新 (转自“袁萌专栏”)
  3. 用xmmp+openfire+smack搭建简易IM实现
  4. C语言实现扫雷小游戏(下)(用递归实现了展开)
  5. ocr简易文字识别v1.41绿色版
  6. 信息安全技术相关的五个误解与谎言
  7. [支付源码]最新京信云易支付整站源码+免签约接口
  8. Beta冲刺(7/7)
  9. go 获得当天0时0分0秒时间戳
  10. python的猜单词小游戏