本节是给C语言初学者字串概念的快览摘要,说明在C里头字元字串如何表示以及一些常见陷阱,假如你已经熟悉这个部份,你可以跳过这一节。
[adsense][/adsense]
字串 是字元物件的阵列,但是字串值变数通常宣告为char *形式的指标,这样的变数不能增加字串文字的空间;以致它们必须储存在某个地方—在阵列变数、字串常数或是动态配置的记忆体中(见记忆体配置),由你决定储存选择记忆体空间位址给指标变数。你也可以储存一个null指标在指标变数中,null指标不指向任何地方,所以尝试参考它指向的字串会产生错误。
“字串”通常指的是多位元组字元字串而不是宽字元字串,宽字元字串是型态wchar_t的阵列而多位元组字元字串通常使用型态wchar_t *的指标。
按照惯例,null 字元、'\0',做为多位元组字元字串的结束,而null宽字元 L'\0',则做为宽字元字串的结束,例如,测试看看char * 变数 p 指向一个null字元做为字串的结束,你可以写 !*p 或 *p == '\0'。
一个空字元跟空指标在概念上是完全不同的,尽管这两个都是用整数0来表示。
字串实字(String literals)在C程式的原始码中以双引号字元间的字元字串来表示以及初始双引号字元前加大写‘L’ (ell)字元(如L"foo"),在ISO C中,字串实字也可以用字串串接t:"a" "b" 或"ab"来形成,对宽字元字串来说,可以用L"a" L"b" 或 L"a" "b",字串实字的修改在GNU C编译器里是不允许的,因为实字被放在唯读记忆体中。
字元阵列被宣告为const也不能修改,宣告不可修改的字串字标为型态const char *通常是比较好的风格,因为这可以允许C编译器侦测意外的修改以及提供一些关于你的程式打算处理字串的文件。
字元阵列记忆体配置的数量可以通过标示字串结束的空字元来扩展,在这份文件里,术语allocated size 用来说明字串记忆体配置的数量,而术语length说明字元数(但不包括)终止的空字元,糟糕的程式错误会试着放更多的字元在字串里而不是以符合其配置的数量来使用,当要撰写增加字串或是移动字元进入已配置的阵列的程式码时,你应该很小心地追踪文字的长度以及对溢出阵列作明确的检查,很多函式库的函式不会为你这件事!也要记得你需要多配置一个位元来持有标记字串结束的空字元。
本来字串是每各位元表示一个单一字元的位元组序列,假如字串使用单位元字元编码的话直到今天仍然是正确的,但是假如字串使用多位元编码的话事情就不一样了(编码的更多资讯见扩充的字元简介),这两种字串的程式设计介面没有不同;程式设计师必须了解这一点并依此解译位元序列。
但因为没有分开介面来留意这些差异导致这些以位元为基础的字串函式有时候很难用,因为这些函式的计数参数会指定位元来呼叫strncpy造成会将多位元字元切成一半,并放置一个未完成(因此不能用)的位元序列在目标缓冲区里。
要避免这些问题新版的ISO C标准介绍了第二组处理宽字元 (见扩充的字元简介)的函式,这些函式没有单一位元版本的问题因为每个宽字元都是合法可解译的值,这不代表在任意点切割宽字元字串是没有问题的,它通常是给以字母为基础的语言使用(除了非正规化的文字)而以音节为基础的语言则仍然有一个宽字元需要完成一个逻辑单元的问题,这是一个C函式库函式未被设计来解决较高层次的问题,但至少好到可以不会产生错的位元序列,而且较高阶的函式在宽字元上比多位元字元上更易操作所以一般的建议是在内部使用宽字元而不用管文字是否只是简单的复制。
本章的其余部份会同时讨论宽字元字串跟多位元字元字串函式的处理因为几乎都有等效的方法可以使用。