字符串在编程里用得非常多。所谓字符串,就是一串字符组成的序列,它是一种常见的数据类型,用来表示和处理文本。这篇我们就来梳理字符串相关的内容:
- 字符串原理
- 字符串和内存
- 字符串操作函数
1. 字符串原理
C 语言里的字符串由一串字符,再加上一个特殊的 \0 字符结尾组成。注意这个 \0 既不是数字 0,也不是字符 0,如下图所示:

为什么要在结尾加上一个 \0 呢?
字符串和 int、double 这类定长类型不一样,它的长度不固定,读的时候没法事先知道它在哪里结束。所以 C 字符串用 \0 当结束符,即:只要知道首字符的地址,我们就一直往后读,直到碰到 \0 为止。
注意:指针不管指向什么类型,存的都是那片数据首元素的地址。
2. 字符串和内存
在 C 里定义字符串有好几种写法,我们得搞清楚每种写法下内存到底分配在哪。下面把各种情况都列出来:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// 1. 第一种情况
// p1 变量存储在全局区,由于 const 修饰,只读
// "hello world" 存储在字符串常量区,只读
const char* p1 = "hello world";
// 2. 第二种情况
// p2 存储在全局区,数组名不允许修改指向,只读
// "hello world" 存储在全局区,可读可写
char p2[] = "hello world";
int main() {
printf("p1 = %s\n", p1);
printf("p2 = %s\n", p2);
// 3. 第三种情况
// p3 存储在栈区,由于 const 修饰,只读
// "hello world" 存储在字符串常量区,程序运行期间不会被销毁,只读
const char* p3 = "hello world";
printf("p3 = %s\n", p3);
// 4. 第四种情况
// p4 存储在栈区,数组名不允许修改指向,只读
// hello world" 存储在栈区,函数结束则会被销毁,可读可写
char p4[] = "hello world";
printf("p4 = %s\n", p4);
// 5. 第五种情况
// p5 存储在栈区,函数结束则会被销毁,可读可写
// "hello world" 存储在堆区,用户决定何时销毁,可读可写
char* p5 = (char *)malloc(strlen("hello world") + 1);
strcpy(p5, "hello world");
printf("p5 = %s\n", p5);
return 0;
}
另外,定义字符串常量时,务必加上 const 修饰。因为标准规定字符串常量不允许修改,但有些编译器却允许这么做,比如下面这段代码在 Borland C++ 里就是合法的:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main() {
char* p = "hello world";
// 下面代码在 VC++ 中是不允许的,在 Borland C++ 中是允许的
p[0] = 'A';
// 为了统一字符串常量的行为,强烈要求同学们如下定义字符串常量
const char *p = "hello world";
// 下面代码无论在 VC++、Borland C++ 行为都是一样的,都禁止修改
p[0] = 'A';
return 0;
}
3. 字符串操作
下面给出 C 字符串常用的操作函数。
- strlen(str):返回字符串 str 的长度(不包括终止符 ‘\0’)。
- strcpy(dest, src):将字符串 src 复制到 dest 中,并返回 dest。
- strncpy(dest, src, n):将字符串 src 的前 n 个字符复制到 dest 中,并返回 dest。如果 src 的长度小于 n,则剩余的字符会用 ‘\0’ 填充。
- strcat(dest, src):将字符串 src 连接到 dest 的末尾,并返回 dest。
- strncat(dest, src, n):将字符串 src 的前 n 个字符连接到 dest 的末尾,并返回 dest。如果 src 的长度小于 n,则剩余的字符会用 ‘\0’ 填充。
- strcmp(str1, str2):比较字符串 str1 和 str2 的大小。如果两个字符串相等,返回 0,如果 str1 小于 str2,返回一个负数,如果 str1 大于 str2,返回一个正数。
- strncmp(str1, str2, n):比较字符串 str1 和 str2 的前 n 个字符的大小。如果两个子字符串相等,返回 0,如果 str1 小于 str2,返回一个负数,如果 str1 大于 str2,返回一个正数。
- strchr(str, c):在字符串 str 中查找字符 c 第一次出现的位置,并返回该位置的指针。
- strrchr(str, c):在字符串 str 中查找字符 c 最后一次出现的位置,并返回该位置的指针。
- strstr(str1, str2):在字符串 str1 中查找字符串 str2 第一次出现的位置,并返回该位置的指针。
- strtok(str, delim):将字符串 str 按照分隔符 delim 进行分割,并返回第一个分割得到的子字符串的指针。




冀公网安备13050302001966号