C字串函式库
目录
简介
C 编程语言在其标准库中有一组函数实现对字符串(字符串和字节串)的操作。支持复制、连接、标记化和搜索等各种操作。对于字符串,标准库使用字符串以 null 结尾的约定:n 个字符的字符串表示为 n + 1 个元素的数组,最后一个元素是 NUL 字符(数值为 0)。
编程语言中对字符串的唯 一支持是编译器将带引号的字符串常量转换为以 null 结尾的字符串。
定义
字符串被定义为由第 一个零代码单元(通常称为 NUL 代码单元)终止的连续代码单元序列。这意味着字符串不能包含零代码单元,因为第 一个看到的标记字符串的结尾。字符串的长度是零代码单元之前的代码单元数。字符串占用的内存总是比长度多一个代码单元,因为需要空间来存储零终止符。
通常,术语字符串表示代码单元为 char 类型的字符串,在所有现代机器上恰好是 8 位。C90 定义了宽字符串,它使用 wchar_t 类型的代码单元,在现代机器上是 16 位或 32 位。这是为 Unicode 而设计的,但在 Unicode 的普通字符串中使用 UTF-8 越来越普遍。
通过将指针传递给第 一个代码单元,将字符串传递给函数。由于 char* 和 wchar_t* 是不同的类型,因此处理宽字符串的函数与处理普通字符串的函数不同,并且具有不同的名称。
字符串文字(C 源代码中的文本)在编译期间被转换为数组。结果是包含所有字符和尾随零代码单元的代码单元数组。在 C90 中,Ltext 生成一个宽字符串。字符串文字可以包含零代码单元(一种方法是将 放入源代码中),但这会导致字符串在该点结束。文字的其余部分将放在内存中(最后添加另一个零代码单元)但不可能知道这些代码单元是从字符串文字翻译而来的,因此这样的源代码不是字符串文字。
字符编码
每个字符串在第 一次出现适当种类(char 或 wchar_t)的零代码单元时结束。因此,字节字符串 (char*) 可以包含 ASCII 或任何 ASCII 扩展中的非 NUL 字符,但不能包含 UTF-16 等编码中的字符(即使 16 位代码单元可能不为零,其高字节或低字节 可能为零)。可以存储在宽字符串中的编码由 wchar_t 的宽度定义。在大多数实现中,wchar_t 至少是 16 位,因此可以存储所有 16 位编码,例如 UCS-2。如果wchar_t是32位的,那么可以存储32位的编码,比如UTF-32。(该标准需要一种包含任何宽字符的类型,自 UCS-2 到 UTF-16 转变后,这在 Windows 上不再适用。)C++11 和 C11 添加了两种具有显式宽度的类型 char16_t 和 char32_t。
可变宽度编码可用于字节字符串和宽字符串。字符串长度和偏移量以字节或 wchar_t 为单位,而不是以字符为单位,这可能会让初学者感到困惑。UTF-8 和 Shift JIS 通常用于 C 字节字符串,而 UTF-16 通常用于 wchar_t 为 16 位时的 C 宽字符串。使用 strncpy 等函数截断具有可变宽度字符的字符串会在字符串末尾产生无效序列。如果被截断的部分由假定输入有效的代码解释,这可能是不安全的。
支持 Unicode 文字,例如 char foo[512] = “φωωβαρ”; (UTF-8) 或 wchar_t foo[512] = L”φωωβαρ”; (UTF-16 或 UTF-32,取决于 wchar_t)是实现定义的,并且可能要求源代码采用相同的编码,尤其是对于 char,编译器可能只复制引号之间的任何内容。一些编译器或编辑器将要求输入所有非 ASCII 字符作为 UTF-8 的每个字节的 xNN 序列,和/或 UTF-16 的每个单词的 uNNNN。 从 C11(和 C++11)开始,一个新的 char foo[512] = u8″φωωβαρ”; 可以使用文字语法来保证字节串文字为 UTF-8。

功能概览
大多数对 C 字符串进行操作的函数都在 string.h 头文件(C++ 中的 cstring)中声明,而对 C 宽字符串进行操作的函数则在 wchar.h 头文件(C++ 中的 cwchar)中声明。这些头文件还包含用于处理内存缓冲区的函数声明; 因此这个名字有些用词不当。
在 string.h 中声明的函数非常流行,因为作为 C 标准库的一部分,它们保证可以在任何支持 C 的平台上运行。