c语言字 字符串转换成数组_我作为自学者对C语言字符串用指针创建和用数组创建的思考...

c语言中,字符串有两种定义方式,分别是:

1. 用星号定义(如:char *ch1 = “helloworld”;)

2. 用数组定义(如:char ch2[20] = “helloworld”;)

备注:假设helloworld字面量存储在常量区里地址为404000的位置上

这两种定义方式,实际上有着很大的差异,以下将以ch1和ch2为例,给大家介绍我对这两种定义方式差异的认识。

差异1:构造字符串的方式不同。

ch1构建过程中,”helloworld”被作为常量字符串储存在内存中的常量区中,如404000这个地址中。ch1作为指针变量,很多情况下,直接指向了这个地址,并没有重新构造一个字符串。

相比之下,ch2则是在内存中又建立了一个新的字符串,这个字符串是根据位于404000上的常量字符串建造的,所以字面量也是helloworld,它的地址可能是62fe10,这与位于404000这个地址上的字符串是两个不同的字符串,只不过其字面量都是helloworld。

差异2:局部修改情况不同。(如ch[0] = ‘a’;语句起的作用不同)

ch1[0] = ‘a’这种形式在c语言中属于未定义的行为,这种语句往往会得到并不想要的结果,原因在《C Primer Plus》中有介绍,印象里比较复杂。

ch2[0] = ‘a’这种表述是允许的,因为ch2并不像ch1一样指向常量区,它的每个字符元素都是可被修改的变量,因此执行这步语句后,ch2字面量将变成“aelloworld”,而在常量区404000上的字符串还是helloworld。

所以,如果需要对字符串进行局部修改,则一般要用数组定义。

差异3:整体修改情况不同。

在进行了文章开头对ch1和ch2的定义后,我们再写下面两行语句,请思考它们的效果。

ch1 = “nihaoshijie”

ch2 = “nihaoshijie”

备注:假设nihaoshijie储存在常量区404109的地址上。

这种操作对于ch1来说,相当于让它不再指向常量区404000上的字符串,而是重新指向了404109上的字符串。所以,ch1的字面量也可以直接更改成nihaoshijie,而不再是helloworld。同理,如果我事先定义了ch3这个字符串并赋值,我接下来让ch1 = ch3,ch1则会重新指向ch3这个字符串,ch1的字面量也会跟ch3的相同。

然而这种操作对于ch2来说就行不通了。大家可能还记得学数组时,定义一个int i[3]={1,2,3},事后是不可以再重新整体赋值的,如i[3] = {4,5,6},这会报错,而且也不可以让它重新等于另一个字符串,即int j[3] = {1,2,3}; int i[3]; i = j也是不被允许的。究其原因,则是因为char ch2[]实际上定义出的ch2是一个字符串常量,就如同int i[4]定义出的实际上是数组常量一样,其地址不能更改,也就是不能让它指向别的字符串或数组。这一点一定要理解好。但是,还是有一种曲线救国可以整体修改的方式,也就是下面的差异4中介绍的这种。

差异4:能否用函数从键盘输入值

对于ch1来说,是不可以从用gets之类的函数从键盘输入值的,它只能事先指向一个已经定义好的常量区字符串或字符串变量。这一点跟数组类似。

对于ch2来说,不管初始化的时候有没有为其赋值,都可以事后通过gets/fgets等函数进行重新赋值,所以涉及到键盘读入时,一定要用ch2来定义。

差异5:处理效率不同

我隐隐记得《C Primer Plus》一书中曾提到,用星号定义的字符串处理速度较快,用数组定义的字符处理速度较慢,但是这一点我不确定。

差异6:函数形参中,样子不同,但实际上效果是相同的

进行函数传参时,不管字符串是怎样定义的,当形参写成以下两种形式,传递的值是相同的。

void f(char *fch);

void f(fchar fch[]);

上面两种情况都是传递了字符串的地址,即首字符的地址。

以上。

文中我反复提到的《C Primer Plus》,也是我看到网上普遍对其评价非常高才阅读的,对我有很大帮助。