前言
在C语言中,追根到底有且仅有两种方式表示字符串——char*和char[]。但是由于指针和数组的关系,这两个方法类似但不完全相同。
char[]
我们知道,char []是一个字符数组,本质上是存储了一个字符串中单独的一个个字符。
#include <stdio.h>
int main(){
char a[3]="abc";
}
在这个数组中,我们的字符串本质上是作为’a’ ‘b’ ‘c’的方式存储数据。
char*
char*作为一个字符指针,是如何进行字符串存储的呢,它与数组类似,开辟了一个连续的空间,并将数据放在其中,char *中则放入这个内存空间的首地址。
#include <stdio.h>
int main(){
char *a="abc";
}
在这个代码中,其实有一个非常需要注意的地方——char*中存放的其实是一个常量,它的值是不允许被修改的。
#include <stdio.h>
int main(){
char *a="abc";
*(a+1)='s';
}
运行结果
Segmentation fault
我们可以看到,编译器编译通过,但运行时抛出了一个错误。
所以在日常中,我们使用的时候最好是在定义前增加一个const,避免编译时无法发现错误。
二者区别
前文我们提到,二者本质上char[]是数组,char*是指针;
所以我们在对字符进行访问的时候,char*可以使用++的自增访问,比如:
#include <stdio.h>
int main(){
char *a = "abc";
printf("%c",*(a));
printf("%c",*(++a));
printf("\n");
}
运行结果
ab
我们可以看到,char*进行了自增访问,并得到了正确的结果。
但char[]无法如此操作,我们知道数组名是一个指针常量,你可以改变它指向的地址的值,但你无法更改它指向的地址
#include <stdio.h>
int main(){
char a[] ="abc";
printf("%c ",*(++a));
printf("\n");
}
运行结果
error: lvalue required as increment operand
printf(“%c “,*(++a));
我们能清晰看到编译器抛出了一个错误。
第二个区别,是赋值区别。
我们可以用char*承接char[]的地址
#include <stdio.h>
int main(){
char a[] ="xyz";
char *p;
p=a;
printf("%c ",*p);
printf("\n");
}
运行结果
x
我们可以看到这里的成功得到了a的值,但是如果我们换一下:
#include <stdio.h>
int main(){
char a[3] ;
char *p ="xyz";
a=p;
printf("%c ",*a);
printf("\n");
}
运行结果
error: assignment to expression with array type
a=p;
编译器抛出了一个错误,所以我们得出来一个结论,char*可以承接char[]的值,但是char[]不能承接char*的值,归根到底,还是char*是一个指针变量,但char[]的数组名是一个指针常量,就样能很好理解为何会造成地址传递出错了。