Delphi中的字符串索引与动态数组索引

Delphi中的字符串索引与动态数组索引,delphi,Delphi,在Delphi中,为什么AnsiStrings从1索引,而动态数组从0索引?这是一个历史性的意外,让翻译更像是短字符串,还是有更深层次的逻辑在起作用?历史性的意外 Pascal字符串和数组通常从1开始 C-可能因此也会有答案-从0开始 我不知道动态数组“打破Pascal传统”的理由,动态数组也是从零开始的。但这是有道理的,我同意 IMHO…基于1的字符串的Delphi字符串传统的原因非常简单。这个传统来自于旧式Turbo-Pascal字符串的实现。该数据类型将字符串的长度存储在变量索引0的第一个

在Delphi中,为什么AnsiStrings从1索引,而动态数组从0索引?这是一个历史性的意外,让翻译更像是短字符串,还是有更深层次的逻辑在起作用?

历史性的意外

Pascal字符串和数组通常从1开始

C-可能因此也会有答案-从0开始

我不知道动态数组“打破Pascal传统”的理由,动态数组也是从零开始的。但这是有道理的,我同意


IMHO…

基于1的字符串的Delphi字符串传统的原因非常简单。这个传统来自于旧式Turbo-Pascal字符串的实现。该数据类型将字符串的长度存储在变量索引0的第一个字节中。字符串数据从下一个字节索引1开始

您今天仍然可以使用该数据类型。它现在被称为短字符串。从它的实现中很明显,有255个字符的限制。如果我没记错的话,这个限制导致在Delphi2中引入了巨大的字符串。当引入大字符串时,语言设计者选择保留基于1的索引,以便于开发人员从短字符串切换到大字符串

我猜Turbo Pascal并没有发明使用元素0表示长度的想法。只是我太年轻了,记不起之前发生了什么

动态数组不再以同样的方式受过去的束缚,而是可以自由选择。我不知道为什么选择零基。也许是因为它更容易适应当时Delphi所处平台上的流行时尚,即Windows。不过这只是猜测而已。丹尼·索普当时从事德尔福编译器的工作,甚至他自己也做过


Delphi语言设计人员目前正朝着基于零的大型字符串索引方向发展。在使用基于0的索引的TStringHelper类中的XE3中可以看到这个方向的初始步骤。而且在ZEROBASEDSTRINGS条件中,允许您选择基于0的索引。希望下一代Delphi编译器只使用基于0的索引。它们的变化时间。

导致“Pascal”字符串被1索引而不是0索引的一个原因是字符串的长度存储在第0个字节中。是的,通过让编译器在内部向字符串索引表达式中添加一个常量偏移量(就像Delphi后面的长字符串中所做的那样),可以从程序员的角度隐藏这一点,但在开始时,事情要简单得多。分配一块内存,将长度存储在字节0中,从字节1索引字符数据。故事结束了

我记得早在Turbo-Pascal出现之前,UCSD-Pascal就以零字节约定使用了这个长度

至于为什么动态数组是基于零的,我不记得任何具体的原因,但我想这反映了动态数组与动态分配缓冲区和索引缓冲区指针的关系。用于创建数组指针类型的数组类型是基于零的数组。第一个字节位于缓冲区指针+0偏移量处。这是基于零的一切的C合理化。当string基于1的索引已经(并且一直)是异常而不是常态时,没有令人信服的理由将string基于1的索引模式带到编译器管理的数组中


很可能是因为字符串类型是每个人第一次遇到的第一个类似数组的数据类型,并且可能是所有人使用最多的数据类型,所以在语言中可能存在对基于1的索引的偏见。然而,如果仔细观察,我认为您会发现Pascal中的数组(不同于string)从来都不是基于1的,特别是在动态分配时

没有传统。在Pascal中,既没有开放数组,也没有动态数组,因此可以用任何语义引入它们。顺便说一句,“C-可能因此AnsiString”是错误的,AnsiString只是Delphi2-2007中常用的字符串,它也以[1]开头。如果数组元素的大小是二的幂,编译器通常可以将索引基调整折叠成x86索引内存加载指令(ModR/M字节)。没有任何性能差异。即使没有mod R/M字节编码技巧,在使用循环索引变量索引到数组的“干净”for循环中,编译器通常能够执行循环归纳(修改for循环索引变量的范围以匹配数组的范围),再次取消索引基调整。@DavidHeffernan“但有时是可测量的”,这与您的第一句话有点不同。>如果你要玩性能卡,我会打电话给你嗯,有趣的东西。Dissasembler编写的代码如下:
mov ebx,[esp+ebx*4-$04]
但这只是一个操作码。因此,无论op看起来多么复杂,芯片都会处理它。我从来不知道这一点,一直在错误的印象下工作。谢谢你帮我澄清,没问题。这就是为什么他们让我们老放屁