转载自:http://blog.sina.com.cn/s/blog_8f99a1640101okxa.html

下面代码:

#include <stdio.h>

int main() {  
    char *cards = "JQK";
    cards[2] = cards[1]; //字符串的值被修改了
    return 0;
}
这段代码可以编译通过,但执行时就会抛出异常。
究其原因就是:字符串是无法更新的!!
 
但修改如下:
#include <stdio.h>

int main() {   
    char cards[] = "JQK"; //注意此处的差别 char* cards改为了 char cards[]
    cards[2] = cards[1]; //字符串的值被修改了 
    return 0;
}
这样代码就可以编译通过,也可以正常运行了。
这是由C语言使用存储器的方式决定的。
可以将 char *cards 添加修饰符 const 变为:const char* cards
 
这样如果修改了字符串的值,在编译的时候就会提示错误。
参考:http://blog.sina.com.cn/s/blog_8f99a1640101okxl.html 的存储器结构来解释下原理:
 
char *cards = "JQK"; 的情况下计算机操作的步骤:
计算机做的步骤:
1. 计算机加载字符串字面值:
当计算机把程序载入存储器时,会把所有常数值(如字符串常量"JQK")放到常量存储区,这部分存储器是只读的。
 
2. 程序在栈上创建cards变量
栈是存储器中计算机用来保存局部变量的部分,局部变量也就是位于函数内部的变量,cards变量就在这个地方。
 
3. cards变量设为"JQK"的地址
cards变量将会保存字符串字面值"JQK"的地址。为了防止修改,字符串字面值通常保存在只读存储器中。
 
4. 计算机试图修改字符串
程序试图修改cards变量指向的字符串中的内容时就会失败,因为字符串是只读的。
 
 
char cards[] = "JQK";的情况下计算机操作的步骤:
1. 计算机加载字符串字面值:
当计算机把程序载入存储器时,会把所有常数值(如字符串常量"JQK")放到常量存储区,这部分存储器是只读的。
 
2. 程序在栈上新建了一个数组
我们声明了数组,所以程序会创建一个足够大的数组来保存字符串"JQK"
 
3. 程序初始化数组
除了为数组分配空间,程序还会把字符串字面值"JQK"的内容复制到栈上。
 
区别:
原来的代码使用了指向只读字符串字面值的指针;而在第二段代码中,用字符串字面值初始化了一个数组,从而得到了这些字母的副本,这样就可以随意修改他们了。