string.h

义项:C语言标准库头文件
string.h

string.h是C语言标准库中负责字符数组与内存块处理的头文件,通过#include <string.h>引入后提供字符串复制、连接、比较、查找、分割以及内存读写等函数原型,并定义 NULL 与 size_t 等符号[1]。该头文件自 C89 起即为必需的标准头之一,是C程序处理以空字符结尾的字符序列的基础设施[2]。由于其中多数函数不检查目标缓冲区边界,使用不当会带来越界风险,C11 另行给出了可选的边界检查版本[3]。

目录
  1. 定义
  2. 原理
  3. 发展历程
  4. 应用
  5. 局限
  6. 参见

定义

string.h是C标准库规定的头文件之一,用于声明一组处理字符数组(C字符串)和通用内存块的函数。程序以#include <string.h>的形式引入它之后,即可使用这些函数的原型;标准同时允许实现把其中部分函数以宏的形式定义[1]。

该头文件还要定义空指针常量 NULL 和类型 size_t,二者在另一个头文件stddef.h中描述;引入string.h时,也可能一并暴露stddef.h中的全部符号[4]。POSIX 标准在其基础上扩展了若干接口,并要求实现提供 locale_t 类型等额外内容[5]。

原理

C语言没有独立的字符串类型,字符串以字符数组的形式存在,并以值为 0 的空字符作为结束标志。因此string.h中的函数大多以指向首字符的指针作为参数,沿着内存逐字节扫描,直到遇到终止符为止[6]。以长度函数为例,strlen 统计的是终止符之前的字符数,返回值不含空字符本身;复制函数strcpy则连同终止符一起搬移[6]。

按操作对象划分,库函数可归为两类。一类作用于以终止符结尾的字符串,如strcpy、strcat、strcmp、strchr、strstr、strtok;另一类作用于任意内存区域,参数中显式给出字节数 $n$,如memcpy、memmove、memcmp、memchr、memset[1]。内存类的函数不理会终止符,因此既能处理二进制数据,也能处理文本。

两类函数在重叠语义上存在区别:memcpy要求源与目标区域没有重叠,否则行为未定义;memmove则保证即使两块区域相互覆盖,结果依然正确。此外,名字中带 n 的版本(strncpy、strncat、strncmp)以长度参数限制处理的字符数,作为对无界版本的补充[6]。

发展历程

string.h在1989年随 ANSI X3.159-1989 成为标准头文件,该标准次年由国际标准化组织以 ISO/IEC 9899:1990 的名义发布,两个编号对应实质上相同的语言与运行库规定,通常合称 C89 或 C90[7]。在 C89 确定的头文件清单中,string.h位列其中,属于托管环境下可以无条件包含的标准头[2]。

1999年的 C99 修订为库补充了新的函数,并把“调用无可见声明的函数”列为需要诊断的约束违反,这使得正确包含头文件成为可移植代码的必需步骤[8]。2011年的 C11 在规范性附录 K 中纳入“边界检查接口”,给出strcpy_s、memcpy_s、strtok_s、memset_s 等带容量参数的版本,但这些接口属于可选特性,实现方可以选择不提供[3]。

附录 K 的接口源自微软在 2004 年安全开发生命周期中推出的一系列“安全”函数,其后被提交给 ISO/IEC JTC1/SC22/WG14 进行标准化[3]。不过,微软自家实现与规范之间存在多处差异,并被指出无法被视为完全一致;同时多年间没有出现被广泛接受的符合性实现,相关提案一度建议将附录 K 删除或先弃用[9]。

应用

在文本处理场景中,string.h承担最基础的搬运与比对工作:读取配置行后复制到缓冲区、拼接路径片段、按字典序比较两个名称、在较长的文本中查找子串,都直接调用这里的函数。分割函数strtok按分隔符集合把一个字符串切成若干片段,常用于解析以逗号或空格分隔的记录[1]。

在内存层面,memset可以把一段区域统一填充为某个字节值,memcpy与memmove用于在对象之间搬运数据,memcmp则按字节比较两块区域。这些函数不依赖字符编码,因而同样适用于结构体、二进制文件和网络报文的处理。

string.h的功能还被大量其他接口复用,例如把错误码转换为说明文字的strerror返回一段描述字符串,供日志输出使用。由于标准库实现普遍内置这些函数,编译器常把它们识别为内建操作并生成优化后的指令序列[10]。

局限

最突出的问题是无界函数不掌握目标缓冲区的大小。strcpy、strcat、strncpy 等只接收指针,若源字符串长于目标容量就会写到边界之外,而 C 语言本身不提供运行时的越界检测[3]。带 n 的版本虽然限制了字符数,但因语义细节容易误用,例如strncpy在源串长度不小于给定上限时不会补上终止符[9]。

另一类限制与并发有关。strtok把“下一次从哪里继续”的状态存放在库内部的静态区域,strerror返回的指针指向由实现管理的共享内存,多个线程同时调用这些函数可能产生数据竞争;C标准并未要求它们避免数据竞争[11]。可行的做法是改用 POSIX 的strtok_r、strerror_r,或使用附录 K 的对应版本[11]。

此外,strlen等函数需要从头逐字节扫描到终止符,复杂度与字符串长度成正比,对超长输入存在性能开销;若字符数组缺少终止符,这类扫描会一直越过数组末尾,属于未定义行为[6]。附录 K 的边界检查版本同样不是万能的:若调用者传入的容量值本身有误,仍可能溢出,因此其防护效果取决于参数是否正确[3]。

参见

  • C语言 —— string.h所属的标准语言及其运行库规范。

  • C标准库 —— 包含string.h在内的标准头文件集合。

  • 空字符结尾字符串 —— string.h中大部分函数所处理的数据形式。

  • 缓冲区溢出 —— 无界字符串函数误用时可能引发的内存错误。

  • POSIX —— 在 C 标准之外对string.h作出扩展的接口规范。

参考资料

  1. string.h [引用日期2026-10-29]
  2. Default Includes (Autoconf) [引用日期2026-10-29]
  3. viewpage [引用日期2026-10-29]
  4. string.h [引用日期2026-10-29]
  5. string.h(0p) [引用日期2026-10-29]
  6. C Guide--2.14 string.h [引用日期2026-10-29]
  7. revisions [引用日期2026-10-29]
  8. 问为什么字符串函数可以在不包含字符串库的情况下工作?EN [引用日期2026-10-29]
  9. revisions [引用日期2026-10-29]
  10. [cfe-dev] C++ Annex K safe C11 functions [引用日期2026-10-29]
  11. diffpagesbyversion [引用日期2026-10-29]
词条评价
词条统计

浏览次数:0 次

阅读量:0 次 · 阅读完成量:0 次

最近更新:2026-10-28T18:37:12Z

历史版本

本条目引用的词条
C语言 C标准库 空字符结尾字符串 缓冲区溢出 POSIX