在Delphi中,字符串索引与动态数组索引的区别

7
在Delphi中,为什么AnsiStrings从1开始索引,而动态数组从0开始索引?这是历史偶然还是为了使AnsiStrings更像ShortStrings,或者有其他更深层次的逻辑在起作用?
3个回答

12

造成“Pascal”字符串从1开始索引而不是从0开始索引的其中一个原因是字符串的长度存储在零字节中。编译器可以在字符串索引表达式中内部添加常量偏移量(如Delphi的长字符串所做的那样),以使程序员看不到这一点,但在最初的阶段,事情要简单得多。分配一块内存,将长度存储在第零个字节中,从第1个字节开始索引字符数据。故事完毕。

据我回忆,UCSD Pascal早在Turbo Pascal出现之前就使用了这种零字节长度约定。

至于为什么动态数组是从零开始的,我不记得有任何具体的原因,但我猜测这反映了动态数组与动态分配缓冲区并索引缓冲区指针的亲属关系。您用于创建数组指针类型的数组类型是从零开始的数组。第一个字节位于缓冲区指针+0偏移处。这是C语言从零开始的一切的理解。当字符串的1基索引已经(并且始终)是个例而不是规范时,没有强制性的理由将字符串的1基索引模式应用到编译器管理的数组上。

很可能是因为字符串类型是每个人首次遇到的第一个类似数组的数据类型,而且可能是跨越整个领域使用最广泛的数据类型,所以可能存在对语言中向1基索引倾斜的感知。但是,如果您仔细查看,我认为您会发现Pascal中的数组(不同于字符串)从未与1基本位相关联,特别是在动态分配时。


1
如果数组元素的大小是2的幂次方,编译器通常可以将索引基础调整折叠到x86索引内存加载指令(ModR/M字节)中。完全没有性能差异。 - dthorpe
1
即使没有使用mod R/M字节编码技巧,在“干净”的for循环中,其中循环索引变量用于索引数组时,编译器通常能够执行循环归纳(修改for循环索引变量的范围以匹配数组的范围),从而消除索引基础调整。 - dthorpe
1
@DavidHeffernan “但有时是可以测量的” 这与你的第一个说法有些不同;> 如果你要玩性能牌,我就要质疑一下。:P - dthorpe
2
嗯,有趣的东西。反汇编器写出的代码是这样的:mov ebx,[esp+ebx*4-$04],但那只是一个单一的操作码。所以无论操作看起来多么复杂,芯片都能处理它。我从未知道这一点,一直在错误的印象下劳作。感谢你让我明白了。 - David Heffernan
1
没问题,这就是为什么他们会留下我们这些老家伙的原因。;> - dthorpe
显示剩余4条评论

4
Delphi字符串从1开始的传统的原因非常简单。这个传统来自于旧版Turbo Pascal字符串的实现。该数据类型在变量的第一个字节(索引0)中存储了字符串的长度。字符串数据从下一个字节(索引1)开始。
今天仍然可以使用该数据类型,它现在被称为ShortString。从其实现中立即显而易见的是,存在255个字符的限制。如果我记得正确,这个限制导致在Delphi 2中引入了huge strings。当huge strings被引入时,语言设计者选择保留1-based索引,以使开发人员更容易从short strings切换到huge strings。
我猜想Turbo Pascal并没有发明使用元素0表示长度的想法。只是我太年轻了,不记得之前发生了什么!
动态数组在过去并没有受到相同的限制,并且具有自由选择。我不知道为什么选择了以零为基础。也许是因为它更容易符合当时Delphi所存在的平台上流行的风格,即Windows。尽管如此,那只是一个猜测。当时Danny Thorpe参与了Delphi编译器的开发工作,但他甚至无法记起理由
Delphi语言设计师目前正在朝着对于大型字符串使用以零为基础的索引移动。这个方向的最初步骤可以在TStringHelper类中看到,该类使用0-based索引。还有ZEROBASEDSTRINGS条件,允许您选择使用0-based索引。预计下一代Delphi编译器将仅使用0-based索引。时代在变化。

0

历史的偶然性。

Pascal字符串和数组传统上从1开始。

C语言 - 也许是因为此 AnsiStrings - 从0开始。

我不知道"打破Pascal传统"在动态数组中的理由,它也从零开始。 但这很有道理,我同意...

在我看来...


2
在 Pascal 程序设计语言中并没有传统意义上的“开放数组”或动态数组,因此可以使用任何语义来引入它们。另外,“C(或许也包括 AnsiStrings)是错误的表述,因为在 Delphi 2 - 2007 中,AnsiString 是通常的字符串类型,同样以 [1] 开始。 - Arioch 'The

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接