为什么Swift String.Index的索引值比实际值大4倍?

时间:2017-11-07 09:01:08

标签: swift string swift-playground

我试图在Swift Playground中实现Boyer-Moore算法,并且我使用了Swift String.Index很多东西并且开始困扰我的原因是为什么索引保持4倍于它应该是的大小。

例如:

let why = "is s on 4th position not 1st".index(of: "s")

Swift Playground中的此代码将生成_compoundOffset 4而不是1.我确信这样做有理由,但我无法在任何地方找到解释。

这不是解释如何在Swift中获取char索引的任何问题的重复,我知道,我使用index(of :)函数来说明问题。我想知道为什么当使用String.Index时,第二个char的值是4而不是1。

所以我猜它保持索引的方式是私有的,我不需要知道内部实现,它可能与UTF16和UTF32编码有关。

1 个答案:

答案 0 :(得分:4)

首先,不要假设_compoundOffset不是实现细节。 _compoundOffsetString.Index的内部属性,它使用位屏蔽在这一个数字中存储两个值:

  • encodedOffset,它是以UTF-16代码单位表示的索引的字节偏移量。这个是公开的,可以依赖。在您的情况下,encodedOffset1,因为这是该字符的偏移量,以UTF-16代码单位衡量。请注意,内存中字符串的编码无关紧要! encodedOffset始终为UTF-16。

  • transcodedOffset,它将索引的偏移存储在当前的UTF-16代码单元中。这也是您无法访问的内部属性。对于大多数索引,该值通常为0,除非您有一个索引到字符串的UTF-8视图中,该视图引用的代码单元不属于UTF-16边界。在这种情况下,transcodedOffset将以encodedOffset为单位存储偏移量。

现在为什么_compoundOffset == 4?因为它将transcodedOffset存储在两个最低有效位中,并将encodedOffset存储在62个最高有效位中。因此encodedOffset == 1, transcodedOffset == 0的位模式为0b100,即4

您可以验证所有这些in the source code for String.Index