为什么字符串使用字符*

Why do strings use char*?

本文关键字:字符 字符串 为什么      更新时间:2023-10-16

为什么 C/C++ stdlibs 中的大多数字符串函数都采用char*指针?

标准中甚至没有指定char的有符号性,尽管大多数现代编译器(GCC,MSVC)默认将char视为有符号。

什么时候将字符串视为(可能)有符号字节才有意义?AFAIK 任何字符集中都没有低于零的有意义的字符值。对于某些字符串操作,无论如何都必须将值强制转换为unsigned char

那么为什么 stdlibs 使用char*呢?甚至C++特定的方法,例如string::string(const char *);

  1. 我很确定大多数字符串函数都早于 unsigned char 的存在。
  2. char可以是有符号类型,也可以是无符号类型。C 和 C++ 标准明确允许其中之一(它始终是与 unsigned charsigned char 不同的类型,但与其中一个具有相同的范围)。
  3. 虽然C字符串函数使用char *,但大多数C++都使用std::string

C 标准在普通char是有符号还是无符号的问题上是不可知的,并且独特地将charsigned char区别对待。此外,基本 ASCII 字符集(包括大多数主要控件和英语可打印字符)由 128 个字符组成,因此可以用有符号char充分表示(至少在任何提供每字节 8 位的系统上)。正如 Jim Balter 指出的那样(见下面的评论),ASCII 并不构成 C 语言的完整基本字符集,但我怀疑它确实包含了大多数常用字符。还有一个庞大的 C 代码语料库依赖于 ASCII 的属性(尽管不一定是 ASCII 独有的)(例如,值为零的NUL特殊字符,按顺序和升序排列的字母数字字符等)。

Jim Balter在评论中指出:

PDP-11 上处理字节的指令将它们视为有符号数量,所以这就是早期 C 编译器处理它们的方式,无符号甚至不存在。

我强烈怀疑这就是为什么默认字符类型char不需要无符号的答案,但需要引用一些书面历史记载才能确定。

至于为什么它也不需要签名(!),在非二的补码机器上,例如(我知道唯一可能仍在使用的)Clearpath Dorado,signed char不能保存unsigned char的所有值,因为它在负零上浪费了一个位模式,或者该位模式用于的任何用途。如果需要对char进行签名,那么将一般数据重新解释为char值序列将是一个问题。因此,在这样的机器上,char必须未签名,否则软件将不得不进行极端扭曲来处理它。

正如 Bjarne 在 The C++ Programming Language 中所说,char是有符号还是无符号取决于实现,C++语言为每个实现提供了两种类型。

其他人已经探讨了当 C 首次被设计和(后来)标准化时它的历史原因,但还有另一个原因为什么这种看似异常现象一直持续到今天。

只是当您将char用于字符时,您不需要知道它是有符号的还是无符号的。标准库提供了可移植的函数,用于对字符进行操作,而不管其表示形式如何。如果你忽略这些功能并坚持对字符进行比较和算术,你应该得到每一个错误。

举一个简单的例子,使用表达式 c >= ' ' 或等效的 c >= 0x20 检查字符是否可打印是很常见的,但您应该改用isprint(c)。这样,您就不会让自己陷入已签名/未签名的混淆,并可能将依赖于平台的错误引入程序。

一旦你养成了使用signed charunsigned char只作为小(通常是 8 位)整数进行算术的习惯,并且在对字符数据进行操作时只使用 char,那么char是一个具有实现定义的符号性的单独类型似乎是完全自然的,更自然的是字符串处理函数总是使用 charchar * 而不是有符号或无符号变体。char的签名性似乎与bool的签名性一样重要。

Char 既

不是有符号的,也不是无符号的。见 https://stackoverflow.com/a/2054941/396583

为什么 C/C++ stdlibs 中的大多数字符串函数都采用 char* 指针?

在C++中,使用std::string。在 C 语言中,引入无符号类型时,使用模式已经过于成熟,我不排除效率问题。

没有低于零的有意义的字符值

那么在C++标准的某个地方有一个约束,即基本字符集中的字符是正数。 但是,认为这种约束适用于所有角色是幼稚的。

该约束强制实现允许EBCDIC作为编码系统使其字符未签名。

大多数现代编译器(GCC,MSVC)默认将char视为签名。

GCC 行为取决于目标,并具有更改目标默认值的选项。