关于C语言中使用变量的字符串赋值:
法一:
int main()
{
char string[10] = "haha";
//改变首字符为H并打印
string[1] = 'H';
printf("Change first: %s\n", string);
//改变首字符为h并打印
*string = 'h';
printf("Change second: %s\n", string);
return 0;
}
编译通过,运行无误;
法二:
int main()
{
char *string = "haha";
string[1] = 'H';
printf("Change first: %s\n", string);
*string = 'h';
printf("Change second: %s\n", string);
return 0;
}
编译警告: [Warning] deprecated conversion from string constant to 'char*' [-Wwrite-strings]
运行结果:程序报错;(段错误)
此处大概就会有人这么说来着:法一与法二都是以一个指向字符串的指针进行首字母变动赋值操作,为什么法二就编译警告且运行出错呢?(这就是本人当初的想法(手动滑稽!!!))
的确,法一与法二的string在一定程度上都可以认为是字符串指针(严格来说,数组名在某些应用场合又区别于指针,但这不是本文重点,详细可参考个人博客:https://blog.csdn.net/YfBong/article/details/90236811),但意义上却相差十万八千里;
先由法二切入,明确来说,
char *string = ""haha";
“haha”这个字符串被当作只读常量处理在C语言(此处不讨论C++)被放置与静态存储区.rodata数据段,string为一个字符型指针,此处为局部变量,存储在栈中,此指针变量存放了“haha”字符串在.rodata中的首地址;
换句话说:此处可声明为: 常量指针:
const char* string = “haha” ;
在修改法二程序:
int main()
{
const char *string = "haha";
string[1] = 'H';
printf("Change first: %s\n", string);
*string = 'h';
printf("Change second: %s\n", string);
return 0;
}
编译会直接报错,而不像一开始一样的仅是一种警告的提醒
根据报错我们可知,程序错在意在修改只读存储区中的只读字符串常量而导致编程出错,添加const做的目的是在于在程序的编译阶段就可以查错,做到防止程序中的某些常量被意外修改而导致程序崩溃。
再说回法一:
为什么法一程序中的“haha”字符串就不是字符串常量呢?
char string[10] = "haha";
关键在于法一中字符串是存储在字符串数组中,程序在运行过程就向栈中申请了一块内存区域作为数组用作字符串赋值,自然而然地可以通过数组来操作字符串了
顺便一提:
当使用printf()输出时,格式化时选择%s,会输出”haha“,这时printf遇到结尾符号‘\0’即停止显示打印,字符串“haha”也是个只读常量,存储在一片连续的内存中,末尾有结尾符表示字符串的结束。
总结:
一般来说,C语言对字符串的变量赋值操作请使用字符串数组,不要使用字符串指针指向一串字符首地址,因为那样会使编译器判断该字符串为只读字符串常量(此时加上const进行常量指针修饰,若该程序有对该字符串进行操作,则在编译阶段就会报错),导致后面程序在对该字符串进行直接操作时崩溃。
以上仅为个人学习理解,不足之处望各位留言区指出,谢谢