之前有一篇文章是学习了字符和字符串的,可以与之结合学习:【C语言进阶深度学习记录】十二 C语言中的:字符和字符串

1 字符串的概念

字符串与字符数组很像,但是有差别,注意留意它们的差别。

  • 字符串是有序字符的集合
  • C语言中,没有字符串的概念(没有string这个关键字,C++中才有)
    1. 但是C语言中,必须使用字符串
    2. 所以C语言通常都是使用特殊的字符数组来模拟字符串
    3. C语言中的字符串,是以’\0’ 结尾的字符数组。也就是说只有字符数组结尾是 ‘\0’ 该字符数组才是字符串,否则该字符数组就是普通的字符数组。这一点很重要!!!

1.1 字符串与字符数组

在C语言中,双引号引用的单个或多个字符是一种特殊的字面量

  • 字面量存储于程序的全局只读存储区
  • 它的本质是字符数组,编译器自动在结尾加上 ‘\0’ 字符。注意,只有双引号下的字面量,编译器才会自动在后面加上’\0’字符。如果是一个普通的字符数组,是要自己在最后加的,否则无法成为字符串。

比如下面哪些是字符串的定义?

  • 第一个ca不是字符串,它是普通的字符数组。
  • sa 也是字符数组,但是由于它末尾加了’\0’,所以它也是一个字符串
  • ss是用双引号初始化的,编译器会默认在最后加上’\0’,所以ss也是字符串
  • 同理str也是字符串

1.2 字符数组与字符串代码分析

  • 代码: 30-1.c
#include <stdio.h>

int main(){
    char ca[] = {'H', 'e', 'l', 'l', 'o'};
    char sa[] = {'H', 'e', 'l', 'l', 'o', '\0'};
    char ss[] = "Hello,World";
    char* str = "Hello,World";
    
    printf("%s\n", ca);
    printf("%s\n", sa);
    printf("%s\n", ss);
    printf("%s\n", str);
    return 0;
}
  • 编译运行结果如下:

  • 可以看出,只有第一个ca打印出来是乱码,后面三个都是正常的。因为ca并不是字符串,我们以 ‘%s’ 打印的话,是类型不对应的,导致打印不对。(深层次原因的话是因为打印字符串都是遇到字符串的结尾’\0’就算打印一个字符串,但是ca中没有’\0’ 字符)

2 字符串字面量

对于字符串的字面量,需要掌握几点:

  1. 字符串字面量的本质是一个数组
  2. 字符串字面量可以看做常量指针,代表存储该字符串的地址
  3. 字符串字面量中的字符不可改变(位于全局只读存储区)
  4. 字符串字面量至少包含一个字符(至少有一个’\0’)

类似于这种 “Hello,world” 是一种无名的字符数组

看一下下面三个表达式是正确的么?如果正确,值是多少?

我们以代码来验证即可:

2.1 字符串字面量的本质的代码分析

  • 代码:30-2.c
#include <stdio.h>

int main(){
    
    char a = "abc"[0]; //==>a='a'
    char b = *("123"+1); //==>b='2'
    char c = *""; //==>c='\0' 它的ASCII码是 0
    
    printf("%c\n", a);
    printf("%c\n", b);
    printf("%d\n", c);   
     
    printf("%s\n", "Hello");
    printf("%p\n", "Hello");
    
    char* p = "def";
    p+=1;
   // *p = 'g'; //error 字符串字面量不能更改
    
    
    return 0;
}
  • 编译运行上述代码结果如下:

可以看出:

  1. 字符串字面量,的确是一个无名数组
  2. 字符串字面量,可以代表它自身的内存地址
  3. 字符串至少包含一个字符’\0’
  4. 字符串字面量存储于全局的只读存储区,不可修改

3 字符串的长度

这是一个比较重要的知识点:

  • 字符串的长度,是指第一个’\0’ 出现之前的所有字符的个数
  • 函数strlen用于返回字符串的长度

如:

3.1 strlen 的使用代码分析

  • 代码30-3.c
#include <stdio.h>
#include <string.h>

int main(){
    
    char s[] = "Hello\0World";
    int i = 0;
    
    for(i=0; i<sizeof(s)/sizeof(char); i++){
        printf("%c\n",s[i]);
    }
    printf("sizeof(s) = %d\n", sizeof(s));
    
    printf("%s\n", s);
    
    printf("%d\n", strlen(s));
    printf("%d\n", strlen("123"));
    
    return 0;
}
  • 编译运行结果为:

可以看到:

  1. sizeof求解字符串的大小时,会将最后的隐藏字符’\0’ 也算进去
  2. strlen求解字符长度时,是求解的字符串中第一个’\0’ 之前的所有字符的个数

4 总结

  • C语言中可以通过字符数组模拟字符串
  • C语言中的字符串是以 ‘\0’ 作为结尾字符
  • 字符串字面量的本质是一个无名的字符数组
  • 字符串的相关函数都依赖于最后的结束符 ‘\0’