不同类型定义展示:
char string []="hello world";
char *string="hello world";
当分别对hello world 进行修改时候:
1.对数组中的hello world 进行修改时我们一般采取数组小标进行修改。如下
string[0]='a';
可以看见很直接的更改成功了。
2.对用指针定义的hello world进行修改我们也可采用下标的形式进行修改。如下
string[0]='a';
结果非常明显引发了权限冲突。
可能有一些同学,做过这方面题知道错误的一种说法是常量不可以修改。但是根本是什么呢那我们接下来就来探讨一下。
刨析:
知识点一:内存四区,对于初学者而言大家都知道如何在电脑中运行自己编写的代码,但是往往忽略了代码本身在计算机中内存发分配。主要分为一下四个区。
1.栈区: 由系统进行内存的管理。主要存放函数的参数以及局部变量。在函数完成执行,系统自行释放栈区内存,不需要用户管理。
2.堆区:由编程人员手动申请,手动释放,若不手动释放,程序结束后由系统回收,生命周期是整个程序运行期间.使用malloc或者new(c++中)进行堆的申请,堆的总大小为机器的虚拟内存的大小。
3. 全局区: 全局/静态存储区内的变量在程序编译阶段已经分配好内存空间并初始化。这块内存在程序的整个运行期间都存在,它主要存放静态变量、全局变量和常量。
4.代码区:存放程序体的二进制代码。比如我们写的函数,都是在代码区的。
内存分析:
由上面的基础知识我们就可以知道"hello world"这行字符串是常量应该存储在全局区是不能被修改的我们只是具备读的权限没有写的权限,这也是我们上边报权限冲突的一个本质原因。
很明显我们可以分析出string这个变量在mian函数中定义的是一个局部变量,它随着main函数的结束而被释放。
画图展示:
如图可以看出,变量类型为指针时直接是将hello world在全局区的地址赋值给了变量p1。当变量类型为数组时候是将全局区的hello world拷贝一份给数组p2,通过p2进行更改时改变的是栈区的hello world对堆区的hello world没有任何影响。
由代码可以展示p1,p2指向的并不是同一块地址说明p2中的hello world是拷贝过来的
在此基础上我们可以们可以在定义一个指字符针类型的变量p3="hello wrold"它的指向的地址依然是和p1一样任然是堆区的hello world计算机很智能的将同一常量反复利用以免内存过大开销。
总结:
当我们我们试图修改用字符数组定义的字符串时实际修改的是全局区拷贝到栈区的字符串,修改的是栈区里的字符串,栈区的是可以被修改的。而我们要是修改用字符指定义的字符串时,它是通过指针直接指向全局区的字符串常量,而在全局区的字符串常量是不可以被更改的(常量本身就不能不更改);由此也可以看出字符串在在被赋值给指针是是进行的地址的赋值,而在对数组类型进行赋值时是进行的值直接的拷贝。