引言:在C++中,对于字符串的操作,我们常使用 String 类,使用起来极其方便,所有常常会用到的对字符串的操作均已封装好。但是,在C中,字符串我们使用字符数组来实现,而且如果不搞清楚字符数组与字符串之间的关系,常常会出现一些无法解释的问题。笔者之前一直对两者之间的关系有所疑惑,最近查阅相关资料,终于搞清楚,现整理出来。虽然这个不算什么大问题,但是不彻底搞清楚就是觉得心里不爽~希望各位看官批评指正。
首先,在这里写下字符数组最简单的定义并初始化的方法:
char str[10]={'H','e','l','l','o','!'};
在这里只需注意以下几点:
1.“Hello!”数组元素个数为6个,它的个数必须小于定义数组的数组大小即10。
2.其余已被申请但未被赋值的内存均被赋值为 '\0'(ASCII:0),也就是说现在str数组中内存赋值情况如下:
地址 | 内容 |
str | 'H' |
str+1 | 'e' |
str+2 | 'l' |
... | 'l' |
... | 'o' |
... | '!' |
str+6 | '\0' |
str+7 | '\0' |
str+8 | '\0' |
str+9 | '\0' |
ASCII中0~31为“非打印控制字符”,其中例如 0号对应的’\0‘ ,13号对应的回车键,将它们按字符的形式打印到屏幕上的时候均为“ ”,它和空格 “ ” 是有本质上的区别。空格对应的ASCII为32号,它属于“打印字符”,只不过空格在屏幕上的表现形式也为 “ ” ,与无法打印的非打印控制字符显示的效果一样罢了。’\0‘仅仅作为一个字符串结束标志存在着,它的作用就是一个标志!
接下来,谈一下C语言中的字符串:
同样地,先写一下字符串最简单的声明定义方式,
1. char str[]={"Hello World !"};
2. char str[]="Hello World !";
以上两种方式等价。但是下面这种方式是错误的!
3. char str[];
str="Hello World !";
为什么第三种方式是错的呢?这就需要了解在执行前两种方式的语句时,计算机做了什么。首先当我们指明要赋的值为"Hello World !"时,计算机会在内存中开辟一个能够装下这个值的内存空间,这也就是为什么str[]的“[]”中不需要写一个具体数值的原因,需要多大计算机已经帮你算好。而如果我们采用第三种方式,会报这样的错:“storage size of 'str' isn't known” 意思就是大小不明。
但是如果想要在声明这个字符串时并不赋值的话,可以采用下面这种方式:
4. char * str;
str="Hello World !";
当然,更直接的方式:char *str="Hello World !"; 也是允许的。
那么,为什么第四种方式又是可行的呢?执行这条语句的时候,计算机同样为"Hello World !"开辟了一定大小内存空间,但是这条语句是将这个内存空间的首地址赋值给str指针,执行 char str[] 语句后,虽然str也是一个指针类型,但是任何数组名的那个指针都是一个常指针!!!!跟其他常量一样,它是不能再被赋值的!用以下方式可以证明:
char *str="Hello World !";
str++;
printf("%c",*str);//结果输出为’e‘
而采用以下方式,直接报错。原因就是下面的str为常指针,不能被重新赋值,也就是str++;是错误的。
char str[]="Hello World !";
str++;
printf("%c",*str);
但是第4种利用指针的写法也有它的局限性,以下面的代码为例:
char *str="Hello!";
str[0]=str[1];
printf("%s",str);
执行以上代码时,程序会崩溃掉,而如果将第一句改为 char str[]="Hello!"; 程序就可以正常执行,其中的原因涉及到计算机内部存储器的工作方式。
(这部分转自http://blog.sina.com.cn/s/blog_8f99a1640101okxa.html)
所以,使用指针方式声明的字符串值无法改变。
最后补充一下刚刚提到的'\0'相关的问题。
char str[]="Hello";
char str1[]={'H','e','l','l','o'};
printf("%d\n",sizeof(str));
printf("%d\n",sizeof(str1));
结果:6 5
造成差异的原因就是str被以字符串的形式赋值,它内部的元素其实为 'H','e','l','l','o','\0' 共6个,而str1只是一个单纯的字符数组。
另外C语言中printf("%s",str);提供了按字符串形式输出的控制符号’%s‘,将以上的str和str1按这种方式输出。
printf("%s\n",str);
printf("%s\n",str1);
输出str1的时候可能会跟着一些乱码,原因就是以str1为首地址的接下来几块内存单元中没有'\0',虽然我们未使用的内存中的值应该为'\0',但是这并不一定。而另一种写法:char str[10]={'H','e','l','l','o'}; 它的输出结果中绝对不会夹杂乱码,因为未被赋值的内存会被计算机主动赋值为'\0',这也算是在设计上的巧妙。
以上就是我今天整理的一些C中字符串和字符数组的一些需要特别注意的点,欢迎各位批评指正~