字符串
字符数组 定义一个char类型的字符数组word[],并且使用大括号初始化一些值:
char word[] = {'H','e','l','l','o','!'};
数组内每一个元素如下图: word[]由很多字符连接并有意义,但不是C语言的字符串,只是一个字符数组,原因是word[]不可以使用字符串的方式做运算。
字符串 定义一个char类型的字符串word[],并且使用大括号初始化一些值:
char word[] = {'H','e','l','l','o','!','\0'};
数组内每一个元素如下图: ::: warning 上述字符数组和字符串的区别在于在数组初始化的过程中,在最后加入了“'\0'”。这个“'\0'”表示整数值的0,即可以直接在大括号的末尾直接加上一个“0”,如上图中,数组中最后一个单元为0。这个0使得字符数组word[]变为C语言的字符串。 :::
字符串 对于C语言来说,字符串是以整数0结尾的一串字符。(0和'\0'是一样的,但和'0'不一样)。 ::: tip 某些情况下会强调'\0'是想要的写法,原因是整数0表达的是int类型,可能会是四个字节,而'\0'一定是一个字节。 '0'是一个字符,表达的是ASCII码的0。 ::: 字符串中的0用来标志字符串的结束,0本身不是字符串的一部分,计算字符串的长度时也不包含这个0。 字符串在内存中的存储形式是数组形式,访问形式可以是数组也可以是指针(更多的是以数组形式访问)。 对于C标准库来说字符串处理函数的原型放在一个头文件string.h中。
字符串变量 定义表达字符串的变量的写法:
char *str = "Hello"; //指针*str指向一个字符数组,字符数组中的内容为“Hello”
char word[] = "Hello"; //有一个字符数组,内容为“Hello”
char line[10] = "Hello";
char line[10] = "Hello";表示字符数组line的大小为10个字节,字符串line中共有H e l l o五个字符,加上结尾的“0”,共占用6个字节。 ::: warning 字符串变量在写出字面量后,编译器会自动生成一个结尾的“0”。 :::
字符串常量 类似于"Hello"这样由双引号括起来的东西在C语言中叫做字符串的字面量或字符串的常量。编译器会把这种字符串的字面量或字符串的常量变成一个字符数组放在某个地方。这个字符数组的长度是可以看到的数组长度加上结尾表示结束的0,如字符数组"Hello"的长度等于5+1=6。 当有两个相邻的字符串常量,中间没有任何符号,两个字符串会被自动的连接起来成为一个大的字符串;也可以去掉第一个字符串后面的双引号和第二个字符串前面的双引号,在两个字符串中间加上反斜杠\,组成一个大的字符串。如下:
printf("请分别输入身高的英尺和英寸,"
"如\"5 7\"表示5英尺7英寸");
修改为:
printf("请分别输入身高的英尺和英寸,\
如\"5 7\"表示5英尺7英寸");
::: tip 上述程序中第4行代码中的反斜杠\表示第4行表示的字符串还没有结束,第5行内容仍然是该字符串的一部分。 使用这种写法需要去掉把第五行内容前的tab键,使得字符串另一部分内容紧贴行头,否则tab会在输出结果中体现。 :::
C语言的字符串是以字符数组的形式存在的,因此不能使用传统运算符如加减乘除对字符串做运算,C语言的字符串可以用数组的方式遍历字符串。 C语言初始化字符数组可以使用双引号的字符串字面量。
字符串变量
char *s = "Hello world";
char *表示一个字符指针,s是一个字符串,等于Hello world,Hello world是一个数组。
#include <stdio.h>
int main(void)
{
int i;
char *s = "Hello world";
char *s2 = "Hello world";
printf("&i = %p\n",&i);
printf("s = %p\n",s);
printf("s2 = %p\n",s2);
return 0;
}
&i = 000000000062FE0C
s = 0000000000404000
s2 = 0000000000404000
--------------------------------
Process exited after 0.0159 seconds with return value 0
上述输出结果中,两个相同值的字符串变量s和s2,具有同样的地址,和变量i对比后,可以发现本地变量i的地址在很大的位置,而字符串变量s和s2在很小的地方(C语言中不同的变量所处的位置不一样)。 字符串变量s和s2位于程序代码段,是只读的,如下:
#include <stdio.h>
int main(void)
{
char *s = "Hello world";
s[0] = 'B';
printf("Here's[0] = %c\n",s[0]);
return 0;
}
--------------------------------
Process exited after 3.968 seconds with return value 3221225477
上述程序中,试图修改字符串s的值中的第一个元素,程序编译无报错,无法运行输出结果,原因是字符串变量s位于程序代码段,是只读的,操作系统的保护机制会使得修改程序崩溃。 ::: tip 字符串在编译时刻已经有值时,编译器会将字符串放在一个只能读不能写的位置,然后让指针指向该处。 如果程序中有多处相同的内容,指针会指向同一个位置。 上述程序中字符串变量s,实际类型是const char* s,由于历史原因,编译器接受不带const的写法。 ::: 如果需要修改字符串变量,需要使用数组的方式:char s[] = "Hello world"; ::: warning char *s = "Hello world";表示指针s指向字符串常量Hello world char s[] = "Hello world";表示字符串变量s在本地,将只读的Hello world复制到数组s的位置,此时可以修改。 :::
#include <stdio.h>
int main(void)
{
int i;
char *s = "Hello world";
char s1[] = "Hello world";
s1[0] = 'B';
printf("s = %p\n",s);
printf("s1 = %p\n",s1);
printf("&i = %p\n",&i);
printf("Here's1[0] = %c\n",s1[0]);
return 0;
}
s = 0000000000404000
s1 = 000000000062FE00
&i = 000000000062FE14
Here's1[0] = B
--------------------------------
Process exited after 0.0157 seconds with return value 0
上述程序中,数组s1的值是一个数组,内容也是Hello world,输出s1的位置,和本地变量i的地址对比,并输出修改后的数组中第一个元素,可以发现s1和i的位置都很大,即s1的位置在本地变量处,且s1的数组中第一个元素可以修改。
当需要一个字符串时,指针形式还是数组形式的选择原则:
char *str = "Hello";
&
char word[] = "Hello";
如果写成数组形式,即字符串就在本地,作为本地变量,空间会被自动回收。
如果写成指针形式,不知道字符串的位置,用来表达一个内容只读无需修改的字符串或表达函数参数(如果数组作为函数参数,实际上和指针是一样的);以及做动态分配空间时。
::: tip
构造一个字符串————>数组
处理一个字符串————>指针
:::
char*是否是字符串
字符串可以表示成char*的形式,char*不一定是字符串。
char*只表示有一个指针,指向一个字节或一串连续的在字节,但不一定是字符串。
和int*一样,可以指向一个单个的int字符,也可以指向一个int的数组。
只有当char*所指的位置有结尾的0,才能认为char*所指的是字符串。