c语言中的字符串,我在以前都一直以为是常量(自己学习不精),实际上字符串在赋值给char*的时候是系统现在内存中开辟一段空间,把字符串的内容存入内存中,再把地址赋给char *。
例如这样:
程序段:
程序运行结果:
解释:
我们通过定义了一个变量,例如:int a; 实际上是系统为程序开辟了一段属于变量 a 的内存空间,假设内存地址为aaaaa。我们改变 a的值,比如 本来a=5; 实际上是向内存中的地址为aaaaa的内存空间存入了5的数值,后来的程序句中变成 a=6; 实际上是把内存中的地址为aaaaa的内存空间中存有的5改成了6。我通过指针int *b=&a;
将b指向a后,通过*b=6
,来改变a,实际上a也等于6,实际上也就是aaaaa内存空间的5变成了6。
这时候问题来了,既然字符串在出现的时候会让系统开辟内存空间并且将字符串的数值存入这个内存空间,那我是否能够通过指针来改变这一段内存空间的内容呢?
如果是普通的
char *a="abcd";
a="bcde";
这样的话,也就是先把a指向"abcd"然后再把a指向"bcde"而已了。
但是我想这样:
char *a="abcd";
*a="bcde";
呢?
答案是不行,编译器不会报编译错误,但是在程序运行的时候就会出错。
程序运行到*a="bcde"; 时就卡住,然后非正常退出了。
也就是我们无法通过 向*a赋值一个字符串 这种方式来改变原本存有"abcd"的那一段内存中的内容。
但是书上说到了:
可以通过改变字符串中的一个字符,并且不通过*pl输出,通过直接输出"Klingon"(因为"Klingon"就代表了它所在的那一段内存,就像int a中的变量a代表了a所在的那一段内存) 看到原本的"Klingon" 变成了"Flingon",也就是内存中连续存放着的'K''l''i''n''g''o''n'中的'K'被改变成了'F',变成了'F''l''i''n''g''o''n'。书上也说明了:"实际上在过去,一些编译器由于这方面的原因,其行为难以捉摸,而另一些编译器则导致程序异常中断。"
当我调用"Klingon"这个字符串时候,全局程序都会使用同一个内存中的字符串。如果你通过某个指针上改变了"Klingon"的值,也就是改变了"Klingon"这个字符串内存中的数值,会使得之后的程序调用"Klingon"字符串时,会变成"Flingon"或者是其他的什么。所以系统保护字符串常量不能被修改。
通过书上的例子进行修改:
结果:
直接用指针修改会导致 Segmentation fault 错误,对内存的错误访问
应该是字符串被当做常量,存放在内存常量区由系统保护,所以无法改变