是否有一个与char16_t一起使用的strlen()?

正如问题所说:

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

对于包含BMP之外字符的UTF-16字符串,这两者完全不同。

这是你的基本strlen:

 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个字节),这些function不包含这些内容。

 #include  #include  #include  #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组件视图:

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  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  1b: c3 ret 1c: 8d 74 26 00 lea esi,[esi+eiz*1+0x0] return len; } 20: c3 ret 21: eb 0d jmp 30  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个字节并检查它们是否都为零,因为在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; } 

在Windows上,有wcslen()

无论平台如何,最好不要使用char16_t。 我认为标准委员会在语言中存在错误。

std :: char_traits有这个。

 #include  std::char_traits::length(yourchar16pointerhere);