目录
从0开始记录我的学习历程,我会尽我所能,写出最最大白话的文章,希望能够帮到你,谢谢。
提示:文章作者为初学者,有问题请评论指正,感谢。
字符串的概念
字符串就像是一串珍珠项链。在C语言中,这串珍珠是一系列的字符(比如字母、数字、标点符号等),它们连在一起,形成了一个完整的信息单元。就像珍珠项链一样,每颗珍珠都是项链的一部分,每个字符也都是字符串的一部分。
在C语言中,字符串是以空字符 '\0'
结尾的字符数组。这个空字符告诉计算机字符串在哪里结束,就像项链的扣子一样,标志着项链的结束。所以,即使我们看到的是一串字符,计算机在处理字符串时,实际上是在查找这个结束的标志。
举个例子,如果我们有一个字符串 "hello"
,在内存中,它会被存储为 ['h', 'e', 'l', 'l', 'o', '\0']
。这个 \0
是不可见的,但它对于C语言来说非常重要,因为它标记了字符串的结束。
字符串的地址,是第一个字符的地址。如:字符串“hello ”的地址,其实是字符串中字符’h’的地址。 我们可以定义一个字符指针变量保存字符串的地址, 比如:char *s =”hello” ;
字符串的存储形式: 数组、文字常量区、堆区
-
数组: 当你声明一个字符数组并初始化它,如
char string[100] = "I love C!";
,这个字符串实际上是存储在内存的栈区(如果是局部变量)或静态全局区(如果是全局变量或静态变量)中。这个数组会包含字符串的每个字符,以及一个额外的空字符'\0'
来标识字符串的结束。char string[100] = "I love C!";
在这个例子中,
string
是一个数组,它占用了100个字符的空间,但实际上"I love C!"
只使用了10个位置(包括空字符)。 -
文字常量区: 当你使用字符串字面量初始化一个指针变量时,如
char *str = "I love C!";
,这个字符串实际上是存储在程序的文字常量区中的。这个区域是只读的,你不能修改其中的内容。str
是一个指针,它存储了字符串第一个字符I
的地址。char *str = "I love C!";
这里,
"I love C!"
存储在文字常量区,而str
只是一个指向该区域的指针。 -
堆区: 你可以使用
malloc
或calloc
等函数在堆区动态地分配内存来存储字符串。这种方式允许你在运行时确定字符串的大小,并且需要你在使用完毕后手动释放内存。char *str = (char*)malloc(10); strcpy(str, "I love C");
在这个例子中,
malloc
函数分配了10个字节的内存,并将地址赋给了str
指针。然后使用strcpy
函数将"I love C"
复制到分配的内存中。注意,这里分配的内存大小应该包括空字符'\0'
。
字符串的可修改性
在C语言中,字符串的可修改性确实取决于它们存放的位置。这里有三种情况:
-
存放在数组中: 如果字符串存储在一个数组中,如
char str[100] = "I love C!";
,那么这个字符串是可修改的。因为数组分配在栈区或静态全局区,你可以自由地修改数组中的任何元素,包括字符串的字符。char str[100] = "I love C!"; str[0] = 'y'; // 正确,可以修改
这里,
str[0] = 'y';
将字符串的第一个字符从'I'
改为'y'
。 -
存放在文字常量区: 如果字符串是通过指针指向一个字符串字面量,如
char *str = "I love C!";
,那么这个字符串存储在文字常量区,是不可修改的。尝试修改会导致未定义行为,通常是程序崩溃。char *str = "I love C!"; *str = 'y'; // 错误,不可修改
这里,
*str = 'y';
尝试修改文字常量区的内容,这是不允许的。 -
存放在堆区: 如果字符串是通过
malloc
动态分配在堆区,如char *str = (char*)malloc(10);
,那么这个字符串是可修改的。因为你拥有这块内存的所有权,可以自由地修改它。char *str = (char*)malloc(10); strcpy(str, "I love C"); *str = 'y'; // 正确,可以修改
这里,
*str = 'y';
将动态分配的字符串的第一个字符从'I'
改为'y'
。
初始化
字符数组初始化: 就像你有一个空盒子,你可以一开始就决定放什么东西进去。比如:
char buf_aver[20] = "hello world";
这里,buf_aver
是盒子,"hello world"
是你放进盒子的东西。
指针指向文字常量区,初始化: 就像你有一个标签,上面写着 "hello world"
的地址。你不能改变地址上的内容,但你可以改变标签上的地址。
char *buf_point = "hello world";
这里,buf_point
是标签,它指向的 "hello world"
是不可改变的内容。
指针指向堆区,堆区存放字符串: 就像你租了一个储物柜,然后把你的东西放进去。你可以随时改变储物柜里的东西。
char *buf_heap = (char *)malloc(15);
strcpy(buf_heap, "hello world");
这里,buf_heap
是储物柜的钥匙,"hello world"
是你放进储物柜的东西。
使用时赋值:
-
字符数组: 你可以用
strcpy
或scanf
来改变盒子里的东西,但不能直接给盒子贴上新的标签。char buf[20]=”hello world” buf="hello kitty"; 错误, 因为字符数组的名字是个常量,不能用等号给常量赋值。 strcpy(buf,"hello kitty");正确,数组中的内容是可以修改的 scanf("%s",buf); 正确,数组中的内容是可以修改的
-
指针指向文字常量区: 你可以改变标签上的地址,但不能改变地址上的内容。
char *buf_point = “hello world”; buf_point="hello kitty"; 正确,buf_point 指向另一个字符串 strcpy(buf_point,"hello kitty"); 错误,这种情况,buf_point 指向的是文字常量区, 内容只读。 当指针指向文字常量区的时候,不能通过指针修改文字常量区的内容。
-
指针指向堆区: 你可以改变储物柜里的东西,也可以换一个储物柜。
char *buf_heap = (char *)malloc(15); strcpy(buf_heap, "hello world"); // 正确 scanf("%s", buf_heap); // 正确
字符串和指针总结:
1 、指针可以指向文字常量区
- 1.指针指向的文字常量区的内容不可以修改
- 2.指针的指向可以改变,即可以给指针变量重新赋值,指针变量指向别的地方。
2 、指针可以指向堆区
1.指针指向的堆区的内容可以修改。
2.指针的指向可以改变,即可以给指针变量重新赋值,指针变量指向别的地方。
3 、指针也可以指向数组(非 const 修饰)
例:char buf[20]="hello world"; char *str=buf;
这种情况下
1.可以修改 buf 数组的内容。
2.可以通过 str 修改 str 指向的内存的内容,即数组 buf 的内容
3.不能给 buf 赋值 buf=“hello kitty ”;错误的。
4.可以给 str 赋值,及 str 指向别处。 str=“hello kitty ”
总结
以上就是今天要讲的内容,本文仅仅简单介绍了C语言中字符串和指针,祝愿你我的朋友在学习的路上一帆风顺,也祝愿我会成为一个优秀的嵌入式工程师。