尽管我热爱C和C++,但我还是忍不住选择以null结尾的字符串:

  • 在C
  • 之前存在长度前缀(即Pascal)的字符串
  • 长度前缀字符串通过允许恒定的时间长度查找,可以使几种算法更快。
  • 前缀字符串的长度使导致缓冲区溢出错误更加困难。
  • 即使在32位计算机上,如果允许字符串成为可用内存的大小,则带前缀长度的字符串也只比以空终止的字符串宽3个字节。在16位计算机上,这是一个字节。在64位计算机上,4GB是一个合理的字符串长度限制,但是即使您希望将其扩展为机器字的大小,64位计算机通常也具有足够的内存,使得多余的7个字节属于null参数。我知道原始的C标准是为极差的机器(就内存而言)编写的,但是效率论点在这里并没有卖给我。
  • 几乎所有其他语言(例如Perl,Pascal,Python,Java,C#等)都使用长度前缀的字符串。这些语言通常在字符串处理基准中胜过C,因为它们在使用字符串时效率更高。
  • C++通过std::basic_string模板对此进行了一些纠正,但是普通字符数组期望以null结尾的字符串仍然很普遍。这也是不完美的,因为它需要堆分配。
  • 空终止的字符串必须保留一个字符(即null),该字符不能存在于字符串中,而长度前缀的字符串可以包含嵌入的null。

  • 这些事情中,有几件事比C揭露的要晚,因此C不必了解它们是有道理的。但是,在C出现之前,有几个很简单。为什么会选择空终止的字符串而不是明显的长度前缀呢?

    编辑:由于有些人在上述效率点上要求提供事实(并且不喜欢我已经提供的事实),因此它们源于以下几点:
  • 使用空终止字符串的Concat需要O(n + m)时间复杂度。长度前缀通常只需要O(m)。
  • 使用空终止字符串的长度需要O(n)时间复杂度。长度前缀为O(1)。
  • Length和concat是迄今为止最常见的字符串操作。在某些情况下,以null终止的字符串可能更有效,但这种情况发生的频率要少得多。

  • 从以下答案中可以看出,在某些情况下以null终止的字符串更有效:
  • 当您需要截断字符串的开头并将其传递给某些方法时。即使允许您销毁原始字符串,也无法真正在恒定时间内使用长度前缀来执行此操作,因为长度前缀可能需要遵循对齐规则。
  • 在某些情况下,您只是逐个字符地遍历字符串,则可以保存CPU寄存器。请注意,这仅在您没有动态分配字符串的情况下才有效(因为您必须释放它,因此必须使用保存的CPU寄存器来保存最初从malloc和friends获得的指针)。

  • 以上都不是最常见的长度和连贯性。

    下面的答案中还有一个断言:
  • 您需要截断字符串
  • 的结尾

    但这是不正确的-空终止和长度前缀字符串的时间相同。 (以NULL终止的字符串只是在您希望新的结尾处保留一个NULL,长度前缀只是从前缀中减去。)

    最佳答案

    horse's mouth



    Dennis M Ritchie,C语言开发

    09-10 03:28