C风格字符串
在C语言中,没有专门存放字符串的数据类型。
通常以以下三种方式表示:
(1)字符串字面值:
"hello world" //静态存储区(文字常量区)中,不能被修改 纠正:字符常量在代码段!
(2)字符数组:(输出同上,注意最后的'\0')
char str[] = {'h','e','l','l','o',' ','w','o','r','l','d','\0'};
char str[] = "hello world"; //(不同于上述字符串字面值,这个存储在栈区,可以被修改)
(3)字符指针方式:(既可以指向字符串字面值,也可以指向字符数组)
char* str = "hello world";
或者
char str1[] = {'h','e','l','l','o',' ','w','o','r','l','d','\0'}; char* str2 = str1;
在C语言中,所有字符串以一个称为空字符的字符结尾。空字符可以写成'\0'。
上述三种字符串表示方法的区别:
(1)字符串字符值存储在程序的静态存储区纠正:代码区,其值不可被修改。
char* str = "hello"; //字符串字面值,存储在静态区代码区 str[1] = 'c'; //Error! strcpy(str, "world"); //Error!同上 str = "abcde"; //OK!这只是把新的字符常量"abcde"的地址赋给str这个指针变量
其实这里我有点疑惑,我用VS编译通过,运行错误;
但是用gcc编译是可以通过的,运行输出是“hcllo”。导致这种结果,可能应该是实现的差异。
ANSI C说,修改字符串常量的行为是未定义的。
(今天又去Linux上的GCC编译了下,运行时是段错误!上面那个我是在Cygwin里的GCC编译的才能运行,我想应该是那个编译环境的问题,应该是报错的!)(又据说TC2.0编译也能成功运行...)
一个字符串字面值占据的存储空间,被用来代表不止一个字符串。换句话说,相同内容的2个字符串字面值可能占用同一个地址。
char* str1 = "hello"; char* str2 = "hello"; puts(str2); //输出"hello" str1[1]= 'c'; //修改是未可知的,假设按上述gcc编译通过且运行成功 puts(str2); //输出"hcllo"!!
(2)字符数组存储在内存栈区,其值可以改变,但数组本身地址不可改变。
char str1[] = "hello"; //存储在栈中,可以修改 str1[1] = 'c'; //OK! str1 = "abcd"; //Error!数组名是常量 char str2[] = "abcd"; str1 = str2; //Error! 同上
这个简单,木有问题,若需要修改字符串,建议请用字符数组方式。
(3)字符指针存储的是一个地址,既可以指向字符串字面值,也可以指向字符串数组。对于前者,字符串内容不能被修改;对于后者,则可以修改。
char* str1 = "abcdefg"; char str2[] = "hijklmn"; char* str3 = str1; str3[1] = 'x'; //Error! str3 = str2; str3[1] = 'x'; //OK!
关于其他一些疑惑:
1)在C++中,字符串字面值实际类型为 const char 数组。那为何 char *p = "ABCDEF"也是合法的?看起来一个pointer to const char指针被赋予了pointer to char指针。
因为字符串字面量在C++中存在两种转换,一种转换依据当前上下文环境,另一种遵循数组到指针的转换。
字符串字面量可以被转换为char*而不是const char*类型的指针,这个转换实际上是对旧有代码的兼容,是一个特例,而且被指定为deprecated的。
虽然字符串字面量在C中类型为char[N],在C++中类型为const char[N],但并不说明C中的字符串字面量可以修改,C++的不可以。字符串字面量是否可以修改与实现数组的类型无关,C之所以没有规定为const char[N],还是出于对旧代码的兼容,而C++规定为const char[N]的原因之一是比C更严格的类型安全。无论C与C++都规定对字符串字面量的修改是未定义的,编译器可以自行处理,也的确存在一些允许修改字符串字面量的编译器,例如老一代的编译器TC,编译器不管是否允许修改字符串字面量,都没有违反标准。
引用自http://blog.csdn.net/supermegaboy/article/details/4854987
2)待补充。。。