数组、指针、字符串(三)探究字符数组、字符指针和字符串的相互联系
2017-03-27 23:14
429 查看
要想正确合理的使用某一项技术,首先要了解清楚的了解它们的概念,做到以不变应万变。
字符数组:元素是字符变量的数组,可以修改数组元素的值。
字符指针:指向某个字符地址的指针。
字符串:存储域静态区,以‘\0’作为结束标志的字符数组,不可以修改字符串内容。
下面通过例子来深入探究三者之间的联系
#include <stdio.h>
int main()
{
char array1[] = {'H','e','l','l','o'};
char array2[] = "Hello";
char *p1 = "Hello";
char *p2 = array1;
char *p3 = array2;
//F9断点处
return 0;
}
F5调试跑起来:
通过上面三者的概念,配合监视中显示的信息,我们可以清晰的了解编译器是如何区分它们的。
在监视中输入如下相关信息,可以发现其中奥秘
1,
对比array1和array2的不同,可以发现。
编译器对于它俩的类型分配是不同的。array数组元素个数是5,array2数组元素个数是6。数组array2比数组array1结尾多了个字符'\0',表示字符串的结束。而array1则没有。说明字符串除了含有'H','e','l','l',o'外,它结尾还含有一个'\0'字符,然后赋给了array2。
这导致了,在对数组array1和数组array2进行解析时,编译器从array1开始往后解析,直到‘\0’结束,最终访问越界,访问未初始化空间,即“烫烫烫”。而对array解析时,访问到'\0'时就表明该数组结束。
2,
对比p1,p2,p3类型,它们三个都是字符指针char *类型。它们指向的是某一字符串或数组的首字符地址。和上面相似,p1和p2的输出都是"Hello",而p2则没有'\0'的限制,越界访问。
另外,虽然p1,p2,p3指向的都是'H'这个字符,但是,三个字符‘H’的位置是不同的,它们分别在静态区或者栈上不同的位置,只是刚好,指向的字符都是‘H’而已。我们可以发现p1,p2,p3地址分别是0x00fe573c,0x00cff789,0x00cff788,表明,它们指向字符'H'的地址不同。
有了上面的基本了解。理解下面的注意事项比较简单了。
相关注意事项:
1,对于,字符串来说,由于它的长度是可变的,没有限制,因此无法自己记录自己的长度。但是由于字符串是连续存储,所以以‘\0’作为自己结束的标志。仅通过一个指向其开头字符的字符指针就能实现对整个字符串的引用。
2,如果用一个字符串字面常量来初始化一个字符数组,数组的长度至少要比字符串字面常量的长度大1,因为还需保存结束符‘\0’。
3,对于字符数组来说,他并不在乎中间或末尾有没有'\0'结束字符。因为数组直到它自己有多少个元素,况且‘\0’字符对它来说是一个合法的元素。
4,当把字符数组当做字符串来使用,可能使用字符指针来引用一个字符数组,在这种情况下,用来操作字符串的库函数(strcpy,strlen等)并不知道这个字符串是来自一个字符数组,因为传递的仅仅是一个字符数组,不包含除了他的类型和值之外的其他信息。这些库函数,会从字符指针开始一直往后访问,直到遇到'\0'为止。很可能就造成“内存访问冲突”或篡改了其他的内存单元。
5,如果能够保证采用数组下标来访问字符数组中的每个元素,那么就没有必要在字符串数组的结尾放进‘\0’。但是我们都无法做出这样的保证,因为大多数情况,我们会把字符数组当做一个字符串的缓冲区,可能发生上述4中的错误。所以最好结尾添加一个'\0'。
6,不能用"="来给字符串赋值,不能用"==",">=","<=="来比较两个字符串,分清楚到底是在对字符串内容还是字符串的首地址进行操作。
字符数组:元素是字符变量的数组,可以修改数组元素的值。
字符指针:指向某个字符地址的指针。
字符串:存储域静态区,以‘\0’作为结束标志的字符数组,不可以修改字符串内容。
下面通过例子来深入探究三者之间的联系
#include <stdio.h>
int main()
{
char array1[] = {'H','e','l','l','o'};
char array2[] = "Hello";
char *p1 = "Hello";
char *p2 = array1;
char *p3 = array2;
//F9断点处
return 0;
}
F5调试跑起来:
通过上面三者的概念,配合监视中显示的信息,我们可以清晰的了解编译器是如何区分它们的。
在监视中输入如下相关信息,可以发现其中奥秘
1,
对比array1和array2的不同,可以发现。
编译器对于它俩的类型分配是不同的。array数组元素个数是5,array2数组元素个数是6。数组array2比数组array1结尾多了个字符'\0',表示字符串的结束。而array1则没有。说明字符串除了含有'H','e','l','l',o'外,它结尾还含有一个'\0'字符,然后赋给了array2。
这导致了,在对数组array1和数组array2进行解析时,编译器从array1开始往后解析,直到‘\0’结束,最终访问越界,访问未初始化空间,即“烫烫烫”。而对array解析时,访问到'\0'时就表明该数组结束。
2,
对比p1,p2,p3类型,它们三个都是字符指针char *类型。它们指向的是某一字符串或数组的首字符地址。和上面相似,p1和p2的输出都是"Hello",而p2则没有'\0'的限制,越界访问。
另外,虽然p1,p2,p3指向的都是'H'这个字符,但是,三个字符‘H’的位置是不同的,它们分别在静态区或者栈上不同的位置,只是刚好,指向的字符都是‘H’而已。我们可以发现p1,p2,p3地址分别是0x00fe573c,0x00cff789,0x00cff788,表明,它们指向字符'H'的地址不同。
有了上面的基本了解。理解下面的注意事项比较简单了。
相关注意事项:
1,对于,字符串来说,由于它的长度是可变的,没有限制,因此无法自己记录自己的长度。但是由于字符串是连续存储,所以以‘\0’作为自己结束的标志。仅通过一个指向其开头字符的字符指针就能实现对整个字符串的引用。
2,如果用一个字符串字面常量来初始化一个字符数组,数组的长度至少要比字符串字面常量的长度大1,因为还需保存结束符‘\0’。
3,对于字符数组来说,他并不在乎中间或末尾有没有'\0'结束字符。因为数组直到它自己有多少个元素,况且‘\0’字符对它来说是一个合法的元素。
4,当把字符数组当做字符串来使用,可能使用字符指针来引用一个字符数组,在这种情况下,用来操作字符串的库函数(strcpy,strlen等)并不知道这个字符串是来自一个字符数组,因为传递的仅仅是一个字符数组,不包含除了他的类型和值之外的其他信息。这些库函数,会从字符指针开始一直往后访问,直到遇到'\0'为止。很可能就造成“内存访问冲突”或篡改了其他的内存单元。
5,如果能够保证采用数组下标来访问字符数组中的每个元素,那么就没有必要在字符串数组的结尾放进‘\0’。但是我们都无法做出这样的保证,因为大多数情况,我们会把字符数组当做一个字符串的缓冲区,可能发生上述4中的错误。所以最好结尾添加一个'\0'。
6,不能用"="来给字符串赋值,不能用"==",">=","<=="来比较两个字符串,分清楚到底是在对字符串内容还是字符串的首地址进行操作。
相关文章推荐
- 字符串string 字符数组与指向字符串的指针pchar的区别与联系
- 字符串,字符数组,字符指针的区别与联系
- 字符指针,字符数组,双引号的字符串的区别与联系
- C/C++字符串,字符数组,字符指针及其相互静态拷贝与追加的安全问题解决方案(2)
- C/C++字符串,字符数组,字符指针及其相互静态拷贝与追加的安全问题解决方案(1)
- java中字符数组和字符串的相互转换
- 字符串指针和字符数组的区别
- 字符串、字符数组、字符指针
- 字符串指针与字符数组(ZT)
- C语言中字符数组和字符串指针分析
- C语言中字符数组和字符串指针分析
- C语言中字符数组和字符串指针分析
- C字符串、字符数组、指针数组、指向数组的指针 彻底研究
- 字符串指针与字符数组
- C/C++(字符串处理)字符指针、字符数组用法大总结
- 使用字符串指针变量与字符数组的区别
- 字符串指针与字符数组的区别
- 字符串、字符数组、字符指针
- 函数内 声明一个字符数组和一个指向字符串数组的指针 区别
- 字符串、字符数组、数组、指针关系总结