简单讨论C中的字符数组相关的问题
1.字符数组跟字符指针有什么区别?
首先我们知道,定义一个字符数组如下:
char arr[ ]= "abbbbbcdfefedfadsf"
定义一个字符指针如下:
char* p2 = "abbbbbcdfefedfadsf";
眨眼一看,感觉确实没什么区别,但我想说的是区别很大。
我们先来了解一下内存的大概存储是如何分布的:
图一:内存的大致分布
假设,数组跟指针都在main函数中定义,从这个图可以看出数组跟指针都是在栈区开辟空间,因为他们都是局部变量;
好,那么我们从知道了他们都在栈区开始,来开始解答为什么区别很大
(1)从初始化角度看是一样的,都是给他们初始赋值成"abbbbbcdfefedfadsf";这个赋值的字符串存储的空间可不是都在栈区。
char arr[ ]= "abbbbbcdfefedfadsf";
char* p2 = "abbbbbcdfefedfadsf";
arr[ ]中的字符串是一种备份,而指针存入的是字符串的地址;
备份跟地址后面再说,先埋个伏笔。
(2)字符数组跟字符指针的功能不同。
你在用char arr[]的时候,虽然不能用arr直接赋值字符串,即 arr = “hello world”;但你可以用arr[ i ],i∈(0~(arr元素个数 - 1)),来改变arr数组的值;
而字符指针的本质就是指向了一个内存空间,只要是有权可以访问,指针就可以指向该内存区域并修改这个区域的值,所以说指针真的不能乱用好吧。
(3)最后来说说,备份跟地址的事。
假设定义int arr[ 10 ] = { 0 };
数组存储的时候,其实是在栈区开辟了一块连续的存储空间;第一个元素arr[ 0 ]为最低的地址,每次地址+1时,依次访问后面的元素,当地址+9时,访问的元素就是arr[ 9 ]。而初始化为0,其实就是把arr[ 0 ] = 0;arr[ 1 ] = 0;......arr[ 9 ] = 0。这就是所谓的备份;
那么在char arr[ ]= "abbbbbcdfefedfadsf" 这句当中,实际就是把每个字符给到对应元素中,最后一个元素就是放了‘\0’表示字符串结束,当你调试VS或者VC的时候,就可以看到arr[ 0 ] = ‘a’;arr[ 0 ] = ‘b’;......arr[ 18 ] = ‘\0’;
图二:数组的各个元素情况
因为这是对最初版本(就是"abbbbbcdfefedfadsf")的copy,那肯定是可以改的,所以要对某字符串进行修改可以采用字符数组写法;
那指针可以吗?如果你要修改它所指向的字符串,我们就试试吧。
图三:程序挂了
好家伙,程序直接崩了。
那现在我们可以知道定义char* p1 = "abbbbbcdfefedfadsf";p1实际上是不可变的,那这个原因我想大家应该看了最上面的图一就知道了,一般来说p1指向的是一块空间,而你单写一段字符串,像"abbbbbcdfefedfadsf",系统会将这个字符串存储到代码段里,这个代码段可牛了,存储的是一种常量,是不可修改的,固定的值。p1指向了不可修改的空间,你要去改它的值,那当然不行。所以我们一般写这种代码,最好写成 const char* p1 = "abbbbbcdfefedfadsf"; 前面的const是修饰*p1整体,表示不可修改p1所指向的值。
2.这两者定义有何区别?
char arr1 [ ] = "abcd" ①
char arr2 [ ] = {‘a’,‘b’,‘c’,‘d’ } ②
我们在VS19run一下
结果很明显了,arr2实际就只有4个元素,刚开始学习的时候很多小伙伴都是认为这两种没什么区别,结果就导致了一些bug的出现,在以后写代码时,要避免这种小错误;
最后,总结一下
(1)char* p1 = "abbbbbcdfefedfadsf";写法不严谨,最好写成 const char* p1 = "abbbbbcdfefedfadsf";
(2)如果要修改字符串里的值,写成字符数组形式,一般是在函数传参时,需要特别注意;
(3)char arr1 [ ] = "abcd" ,char arr2 [ ] = {‘a’,‘b’,‘c’,‘d’ } 两种写法并不等价;