正如您已经发现的那样,UTF-16 实际上是一种可变宽度编码。因此,您必须扫描字符串以执行准确的字符索引。
幸运的是,很容易判断一个字符是否是多词序列的一部分:UTF-16 中唯一的多词序列(如当前定义)是代理对:[D800-DBFF] 范围内的一个词后跟一个[DC00-DFFF] 范围内的字。因此,当您遇到这样的序列时,请将其视为单个字符。
这可能会满足您的需求:
UChar32 utf16_char_at_index(const wchar_t *s, off_t index) {
while(1) {
if(s[0] >= 0xd800 && s[0] <= 0xdbff) {
/* First half of surrogate pair; check next half */
if(s[1] >= 0xdc00 && s[1] <= 0xdfff) {
/* surrogate pair: skip or return */
if(index == 0) {
return ((s[0] - 0xd800) << 10) | (s[1] - 0xdc00);
}
s += 2;
index--;
continue;
}
/* Otherwise, decoding error...may want to flag error here */
}
if(index == 0) {
return s[0];
}
s++;
index--;
}
}