正如问题所说:
typedef __CHAR16_TYPE__ char16_t;
int main(void)
{
static char16_t test[] = u"Hello World!\n";
printf("Length = %d", strlen(test)); // strlen equivalent for char16_t ???
return 0;
}
我搜索并发现只有C ++解决方案。
我的编译器是GCC 4.7
。
修改
为了澄清,我正在搜索一个返回code points
计数的解决方案,而不是characters
的计数。
对于包含UTF-16
以外字符的BMP
字符串,这两者完全不同。
答案 0 :(得分:4)
这是你的基本格式:
int strlen16(const char16_t* strarg)
{
int count = 0;
if(!strarg)
return -1; //strarg is NULL pointer
char16_t* str = strarg;
while(*str)
{
count++;
str++;
}
return count;
}
这是一个更有效和更受欢迎的strlen:
int strlen16(const char16_t* strarg)
{
if(!strarg)
return -1; //strarg is NULL pointer
char16_t* str = strarg;
for(;*str;++str)
; // empty body
return str-strarg;
}
希望这有帮助。
警告:在计算UTF-16字符串的字符(不是代码点)时,这不能正常工作。将__STDC_UTF_16__
定义为1
时,尤其如此。
UTF-16是可变长度的(BMP中每个字符2个字节或BMP外每个字符4个字节),这些功能不包括这些。
答案 1 :(得分:2)
#include <string.h>
#include <wchar.h>
#include <uchar.h>
#define char8_t char
#define strlen8 strlen
#define strlen16 strlen16
#define strlen32(s) wcslen((const wchar_t*)s)
static inline size_t strlen16(register const char16_t * string) {
if (!string) return 0;
register size_t len = 0;
while(string[len++]);
return len;
}
您应该期望返回char16_t
个字符的数量,而不是字节数。
优化的32位Intel Atom Assembly视图:
gcc -Wpedantic -std=iso9899:2011 -g3 -O2 -MMD -faggressive-loop-optimizations -fkeep-inline-functions -march=atom -mtune=atom -fomit-frame-pointer -mssse3 -mieee-fp -mfpmath=sse -fexcess-precision=fast -mpush-args -mhard-float -fPIC ...
.Ltext0:
.p2align 4,,15
.type strlen16, @function
strlen16:
.LFB20:
.cfi_startproc
.LVL0:
mov edx, DWORD PTR 4[esp]
xor eax, eax
test edx, edx
je .L4
.p2align 4,,15
.L3:
.LVL1:
lea eax, 1[eax]
.LVL2:
cmp WORD PTR -2[edx+eax*2], 0
jne .L3
ret
.LVL3:
.p2align 4,,7
.p2align 3
.L4:
ret
.cfi_endproc
.LFE20:
.size strlen16, .-strlen16
这是英特尔反汇编:
static inline size_t strlen16(register const char16_t * string) {
0: 8b 54 24 04 mov edx,DWORD PTR [esp+0x4]
if (!string) return 0;
4: 31 c0 xor eax,eax
6: 85 d2 test edx,edx
8: 74 16 je 20 <strlen16+0x20>
a: 8d b6 00 00 00 00 lea esi,[esi+0x0]
register size_t len = 0;
while(string[len++]);
10: 8d 40 01 lea eax,[eax+0x1]
13: 66 83 7c 42 fe 00 cmp WORD PTR [edx+eax*2-0x2],0x0
19: 75 f5 jne 10 <strlen16+0x10>
1b: c3 ret
1c: 8d 74 26 00 lea esi,[esi+eiz*1+0x0]
return len;
}
20: c3 ret
21: eb 0d jmp 30 <AnonymousFunction0>
23: 90 nop
24: 90 nop
25: 90 nop
26: 90 nop
27: 90 nop
28: 90 nop
29: 90 nop
2a: 90 nop
2b: 90 nop
2c: 90 nop
2d: 90 nop
2e: 90 nop
2f: 90 nop
答案 2 :(得分:0)
你需要读取2个字节并检查它们是否都是零,因为unicode第一个字节可以为零。
不是一个完美的解决方案(实际上是一种奇怪的解决方案):
size_t strlen16(const char16_t* str16) {
size_t result = 0;
char* strptr = (char*) str16;
char byte0, byte1;
if(str16 == NULL) return result;
byte0 = *strptr;
byte1 = *(strptr + 1);
while(byte0|byte1) {
strptr += 2;
byte0 = *strptr;
byte1 = *(strptr + 1);
result++;
}
return result;
}
答案 3 :(得分:0)
在Windows上,有wcslen()
。
无论平台如何,最好不要使用char16_t。我相信标准委员会的blunder是用语言表达的。{/ p>
答案 4 :(得分:0)
std::char_traits有这个。
#include <string>
std::char_traits<char16_t>::length(yourchar16pointerhere);