char * 与char []探究理解
问题引入
以前一直认为二者是一样的,今天突然发现他们还是有很大的不同的。例如char *a = "abc"和char b[] = "abc",当我使用strcat(b,a)时得到的b是二者的结合,当我使用strcat(a,b)时系统报错。也就是说前者改变其内容程序是会崩溃的,而后者完全正确。
预备知识
内存分配的三种方式方式:静态存储区、堆区和栈区。它们的功能不同,使用方式也就不同。
1.静态存储区:内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。它主要存放静态数据、全局数据和常量。
2.栈区:在执行函数时,函数(包括main函数)内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。(任何变量都处于站区,例如int a[] = {1, 2},变量a处于栈区。数组的内容也存在于栈区。)
3.堆区:亦称动态内存分配。程序在运行的时候用malloc或new申请任意大小的内存,程序员自己负责在适当的时候用free或delete释放内存。动态内存的生存期可以由我们决定,如果我们不释放内存,程序将在最后才释放掉动态内存。 但是,良好的编程习惯是:如果某动态内存不再使用,需要将其释放掉,并立即将指针置位NULL,防止产生野指针。
解决问题
回到问题上来,我们来举个例子:char *a = "Hello",char b[] = "World",其中a是指向字符串第一个字符'H'的一个指针,b也是指向字符数组第一个字符'W'的指针,但这二者不相同,不同在哪呢?
char *a = "Hello":定义了一个char型的指针a,a在栈上,指向"Hello"所在的内存单元,它不知道这个内存单元有多大。"Hello"存放在常量区,是无法修的。通过指针a只可以访问字符串常量,而不可以改变它。它在编译时就会被确定。
char b[] = "World":定义一个字符数组,在栈上开了一块区域,b为这块区域的首地址。"World"是存放在这块区域中,是可以修改的。可以通过指针b去访问和修改数组内容。它要在运行时才会被确定。
贴段代码理解一下:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std; int main()
{
char *a="Hello";//a在栈上,"Hello"在常数区上
//a[2]='a';//系统错误:不可以修改常数区数据,只能读取
char b[]="Hello";//b在栈上,且为字符串"Hello"的首地址
b[]='a';//可以这样做,可以修改 char *s1=(char*)malloc();//在栈上开辟一个区域放s1,在堆上开辟一个区域,再让s1指向他
char s2[]; while(~scanf("%s %s",s1,s2))
{
char *s3=s2;//此时s3与s2用法一样,因为他们指向同一个在栈上的地方
s3[]='a';
printf("%s %s %s\n",s1,s2,s3);
}
}
结论
在C/C++中,指针和数组在很多地方可以互换使用,这使得我们产生一种错觉,感觉数组和指针两者是完全等价的,事实上数组和指针是有很大的区别的。
数组对应着一块内存区域,而指针是指向一块内存区域,其地址和容量在生命期里不会改变,只有数组的内容可以改变;而指针却不同,它指向的内存区域的大小可以随时改变,而且当指针指向常量字符串时,它的内容是不可以被修改的,否则在运行时会报错。
用运算符sizeof可以计算出数组的容量(字节数),而用sizeof却无法计算指针所指内存的容量,用sizeof(p)得到的结果永远是4或者2(即指针变量所占内存单元的字节数,一般情况下指针变量占2个或4个字节的内存单元)。在进行参数传递时,数组会自动退化为同类型的指针。
在使用过程中,我们可以给char*开辟空间,例如char *s=(char*)malloc(64);这个空间实在堆上的,使用起来就和字符数组很像了(几乎一样)
char* 类型使用总结:http://blog.csdn.net/z702143700/article/details/46628251
C语言字符串处理函数:http://www.cnblogs.com/alaigle/archive/2012/05/24/2516062.html
作者: AlvinZH
出处: http://www.cnblogs.com/AlvinZH/
本人Github:https://github.com/Pacsiy/JobDu
本文版权归作者AlvinZH和博客园所有,欢迎转载和商用,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
char * 与char []探究理解的更多相关文章
- <转载>深入 理解char * ,char ** ,char a[ ] ,char *a[] 的区别
C语言中由于指针的灵活性,导致指针能代替数组使用,或者混合使用,这些导致了许多指针和数组的迷惑,因此,刻意再次深入探究了指针和数组这玩意儿,其他类型的数组比较简单,容易混淆的是字符数组和字符指针这两个 ...
- 深入 理解char * ,char ** ,char a[ ] ,char *a[] 的区别(转)
C语言中由于指针的灵活性,导致指针能代替数组使用,或者混合使用,这些导致了许多指针和数组的迷惑,因此,刻意再次深入探究了指针和数组这玩意儿,其他类型的数组比较简单,容易混淆的是字符数组和字符指针这两个 ...
- 【转】深入理解const char*p,char const*p,char *const p,const char **p,char const**p,char *const*p,char**const p
一.可能的组合: (1)const char*p (2)char const*p (3)char *const p(4)const char **p (5)char const**p (6)char ...
- 对 const char* const &a 的理解
定义中用到&是独立引用. 比如: char i; char &a=i; 表示a是i的一个单独引用. 当有i='a'时,也有a='a'; 当有a='c'时,也有i='c'; 两个变量的标 ...
- 深入理解char * ,char ** ,char a[ ] ,char *a[]
1.数组的本质 数组是多个元素的集合,在内存中分布在地址相连的单元中,所以可以通过其下标访问不同单元的元素. 2.指针 指针也是一种变量,只不过它的内存单元中保存的是一个标识其他位置的地址.由于地址也 ...
- 深入理解const char*p,char const*p,char *const p,const char **p,char const**p,char *const*p,char**const p
由于没有const*运算,const实际上修饰的是前面的char*,但不能在定义时转换写成 const(char *)*p,因为在定义是"()"是表示函数. 三.深入理解7种组合 ...
- 深入 理解char * ,char ** ,char a[ ] ,char *a[] 的区别
转自:https://blog.csdn.net/liusicheng2008_liu/article/details/80412586 1 数组的本质 数组是多个元素的集合,在内存中分布在地址相连的 ...
- 理解C/C++中const char*、char* const、const char* const、char* const*等等
先说些题外话,今天学习execve(2)的使用,由于书上代码使用的是C89标准,所以下面这种代码都被我修改了 char* s[] = { "aaa", "bbb" ...
- 【转】深入 char * ,char ** ,char a[ ] ,char *a[] 内核
原文出处:http://blog.csdn.net/daiyutage/article/details/8604720 C语言中由于指针的灵活性,导致指针能代替数组使用,或者混合使用,这些导致了 ...
随机推荐
- 541. Reverse String II 指定翻转前k个的字符串
[抄题]: Given a string and an integer k, you need to reverse the first k characters for every 2k chara ...
- diskpart setid value list
ntfs : 07 / 17 显示/隐藏 fat32: 0C / 1C 显示/隐藏 0 空 24 NEC DOS 81 Minix / 旧 Linu bf Solaris 1 FAT12 27 隐藏的 ...
- Charles 4.2.5 破解原理.RP
请支持正版,仅供技术交流. 写了个小工具方便在线处理,在线破解 https://github.com/8enet/Charles-Crack 2018/4/8 Charles 4.2.5 替换类名和方 ...
- 编写高质量代码改善C#程序的157个建议——建议146:只对外公布必要的操作
建议146:只对外公布必要的操作 那些没有必要公开的方法和属性要声明成private.如果需要公开的方法和属性超过9个,在VS默认的设置下,就需要滚屏才能显示在Intellisense中,如图: Sa ...
- 编写高质量代码改善C#程序的157个建议——建议143:方法抽象级别应在同一层次
建议143:方法抽象级别应在同一层次 看下面代码: class SampleClass { public void Init() { //本地初始化代码1 //本地初始化代码2 RemoteInit( ...
- sql 两大类 DDL数据定义语言 和DCL数据控制语言
SQL分为五大类: DDL:数据定义语言 DCL:数据控制语言 DML:数据的操纵语言 DTL:数据事务语言 DQL:数据查询语言. DDL (date definition lang ...
- Python 3 Mysql 增删改查
import pymysql import datainfo import time #获取参数 host = datainfo.host username = datainfo.username p ...
- 解决NIOS II工程移动在磁盘上位置后project无法编译问题
说明:本文档于2017年3月4日由小梅哥更新部分内容,主要是增加了讲解以Quartus II13.0为代表的经典版本和以15.1为代表的更新版本之间,解决问题的一些小的差异. 如果用户只是想快速解决问 ...
- src.rpm格式的RHCS源码提取
RHCS源码下载(地址1:地址2) 参考文档(RHCS安装也配置) RHCS源码提取(参考) 方法一: (1)rpm –ivh magma-plugins-1.0.15-3.src.rpm 执行r ...
- Android-ContentProvider理解操作系统的多媒体
在多年以前,我做一款音乐播放器,要把很多.mp3文件,放置在自己新建的文件夹里面,然后去读取这个新建的文件夹里面的音乐列表,现在想想是多么的无知: 因为只要往手机里面放入.mp3文件,系统会自动检测, ...