2012-02-12 23 views
3

我發現,在VC++ 2010和的回報信件正確的計數wcslen();同時Xcode不會。 例如,下面的代碼在VC++ 2010中返回正確的11,但在Xcode 4.2中返回錯誤的17。wcslen()的工作方式不同的Xcode和VC++

const wchar_t *p = L"123abc가1나1다"; 
size_t plen = wcslen(p); 

我想Xcode的應用程序商店wchar_t字符串作爲存儲UTF-8。這是另一件奇怪的事情。

我如何獲得11就像VC++在Xcode嗎?

+0

它工作得很好,對我來說。在源代碼上運行終端上的'hexdump -C sourcefile.c'的輸出是什麼? – 2012-02-12 03:28:31

+0

我從GCC_VERSION = com.apple.compilers.llvm.clang.1_0改變GCC_VERSION = com.apple.compilers.llvmgcc42,結果從17改爲11正確! – 2012-02-12 06:35:43

+0

這是叮噹中的一個錯誤/不受支持的功能,並且自此以後已修復。以前,clang只支持ascii作爲源編碼,它不會將字符串文字從UTF-8轉換爲廣泛的執行字符集。 – bames53 2012-02-16 21:27:59

回答

4

我跑了一臺Mac Mini這個程序運行的MacOS X 10.7.2(Xcode的4.2):

#include <stdio.h> 
#include <wchar.h> 

int main(void) 
{ 
    const wchar_t p[] = L"123abc가1나1다"; 
    size_t plen = wcslen(p); 
    if (fwide(stdout, 1) <= 0) 
    { 
     fprintf(stderr, "Failed to make stdout wide-oriented\n"); 
     return -1; 
    } 
    wprintf(L"String <<%ls>>\n", p); 
    putwc(L'\n', stdout); 
    wprintf(L"Length = %zu\n", plen); 
    for (size_t i = 0; i < sizeof(p)/sizeof(*p); i++) 
     wprintf(L"Character %zu = 0x%X\n", i, p[i]); 
    return 0; 
} 

當我做了源文件的十六進制轉儲,我看到:

0x0000: 23 69 6E 63 6C 75 64 65 20 3C 73 74 64 69 6F 2E #include <stdio. 
0x0010: 68 3E 0A 23 69 6E 63 6C 75 64 65 20 3C 77 63 68 h>.#include <wch 
0x0020: 61 72 2E 68 3E 0A 0A 69 6E 74 20 6D 61 69 6E 28 ar.h>..int main(
0x0030: 76 6F 69 64 29 0A 7B 0A 20 20 20 20 63 6F 6E 73 void).{. cons 
0x0040: 74 20 77 63 68 61 72 5F 74 20 70 5B 5D 20 3D 20 t wchar_t p[] = 
0x0050: 4C 22 31 32 33 61 62 63 EA B0 80 31 EB 82 98 31 L"123abc...1...1 
0x0060: EB 8B A4 22 3B 0A 20 20 20 20 73 69 7A 65 5F 74 ...";. size_t 
0x0070: 20 70 6C 65 6E 20 3D 20 77 63 73 6C 65 6E 28 70 plen = wcslen(p 
0x0080: 29 3B 0A 20 20 20 20 69 66 20 28 66 77 69 64 65 );. if (fwide 
0x0090: 28 73 74 64 6F 75 74 2C 20 31 29 20 3C 3D 20 30 (stdout, 1) <= 0 
0x00A0: 29 0A 20 20 20 20 7B 0A 20 20 20 20 20 20 20 20 ). {.   
0x00B0: 66 70 72 69 6E 74 66 28 73 74 64 65 72 72 2C 20 fprintf(stderr, 
0x00C0: 22 46 61 69 6C 65 64 20 74 6F 20 6D 61 6B 65 20 "Failed to make 
0x00D0: 73 74 64 6F 75 74 20 77 69 64 65 2D 6F 72 69 65 stdout wide-orie 
0x00E0: 6E 74 65 64 5C 6E 22 29 3B 0A 20 20 20 20 20 20 nted\n");.  
0x00F0: 20 20 72 65 74 75 72 6E 20 2D 31 3B 0A 20 20 20  return -1;. 
0x0100: 20 7D 0A 20 20 20 20 77 70 72 69 6E 74 66 28 4C }. wprintf(L 
0x0110: 22 53 74 72 69 6E 67 20 3C 3C 25 6C 73 3E 3E 5C "String <<%ls>>\ 
0x0120: 6E 22 2C 20 70 29 3B 0A 20 20 20 20 70 75 74 77 n", p);. putw 
0x0130: 63 28 4C 27 5C 6E 27 2C 20 73 74 64 6F 75 74 29 c(L'\n', stdout) 
0x0140: 3B 0A 20 20 20 20 77 70 72 69 6E 74 66 28 4C 22 ;. wprintf(L" 
0x0150: 4C 65 6E 67 74 68 20 3D 20 25 7A 75 5C 6E 22 2C Length = %zu\n", 
0x0160: 20 70 6C 65 6E 29 3B 0A 20 20 20 20 66 6F 72 20 plen);. for 
0x0170: 28 73 69 7A 65 5F 74 20 69 20 3D 20 30 3B 20 69 (size_t i = 0; i 
0x0180: 20 3C 20 73 69 7A 65 6F 66 28 70 29 2F 73 69 7A < sizeof(p)/siz 
0x0190: 65 6F 66 28 2A 70 29 3B 20 69 2B 2B 29 0A 20 20 eof(*p); i++). 
0x01A0: 20 20 20 20 20 20 77 70 72 69 6E 74 66 28 4C 22   wprintf(L" 
0x01B0: 43 68 61 72 61 63 74 65 72 20 25 7A 75 20 3D 20 Character %zu = 
0x01C0: 30 78 25 58 5C 6E 22 2C 20 69 2C 20 70 5B 69 5D 0x%X\n", i, p[i] 
0x01D0: 29 3B 0A 20 20 20 20 72 65 74 75 72 6E 20 30 3B );. return 0; 
0x01E0: 0A 7D 0A           .}. 
0x01E3: 

當使用GCC編譯的輸出是:

String <<123abc 
Length = 11 
Character 0 = 0x31 
Character 1 = 0x32 
Character 2 = 0x33 
Character 3 = 0x61 
Character 4 = 0x62 
Character 5 = 0x63 
Character 6 = 0xAC00 
Character 7 = 0x31 
Character 8 = 0xB098 
Character 9 = 0x31 
Character 10 = 0xB2E4 
Character 11 = 0x0 

注意該字符串是在零字節截斷 - 我認爲這是對robably系統中的一個bug,但似乎有點不太可能,我會設法找到一個對我的第一次嘗試使用wprintf(),所以它更可能我做錯了。

沒錯,在多字節UTF-8的源代碼,字符串佔據17個字節(8個單字節基本Latin-1字符和3個字符分別使用3個字節編碼)。因此,源字符串上的原始strlen()將返回17個字節。

GCC的版本是:

i686-apple-darwin11-llvm-gcc-4.2 (GCC) 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.15.00) 
Copyright (C) 2007 Free Software Foundation, Inc. 
This is free software; see the source for copying conditions. There is NO 
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

只是爲了笑聲,我試過clang,我得到不同的結果。編譯使用:

clang -o row row.c -Wall -std=c99 

使用:

Apple clang version 2.1 (tags/Apple/clang-163.7.1) (based on LLVM 3.0svn) 
Target: x86_64-apple-darwin11.3.0 
Thread model: posix 

clang編譯輸出爲:

String <<123abc가1나1다>> 

Length = 17 
Character 0 = 0x31 
Character 1 = 0x32 
Character 2 = 0x33 
Character 3 = 0x61 
Character 4 = 0x62 
Character 5 = 0x63 
Character 6 = 0xEA 
Character 7 = 0xB0 
Character 8 = 0x80 
Character 9 = 0x31 
Character 10 = 0xEB 
Character 11 = 0x82 
Character 12 = 0x98 
Character 13 = 0x31 
Character 14 = 0xEB 
Character 15 = 0x8B 
Character 16 = 0xA4 
Character 17 = 0x0 

所以,現在的字符串顯示正確,但指定的長度爲17個,而不是11.表面上,你可以選擇錯誤 - 字符串看起來不錯(在終端 - /應用程序/實用程序/終端 - 適應UTF8),但長度是錯誤的,或長度是正確的,但字符串沒有正確顯示。

我注意到,在這兩種gccclangsizeof(wchar_t)爲4

左手不明白右手在做什麼。我認爲有一種情況可能會以不同的方式聲稱兩者都被打破。

+0

FWIW,如果你在調用'wprintf'之前調用'setlocale(LC_ALL,「en_US.UTF-8」);''''''''這將和gcc一起工作。這是因爲'wprintf'嘗試將生成的寬字符串轉換爲當前多字節語言環境,該語言環境默認爲C語言環境,它不能處理非ASCII字符,因此它會停止轉換。不知道爲什麼Clang不工作;它看起來沒有正確識別源字符集,但'-finput-charset = UTF-8'選項似乎不起作用。 – 2012-02-12 03:56:48

+0

我添加了'#include '和'setlocale(LC_ALL,「」);'並且'gcc'的輸出確實表現得'正確':'String << 123abc 1나1다>>',其餘的和以前一樣。當修改後的程序使用'clang'編譯時,它產生了'String <<123abcê°1'X >>'(終端看起來與預覽中的瀏覽器不同,儘管在保存註釋之後它似乎更好; X是一個有4個剔出角的廣場,我認爲是國際貨幣符號)。這17個字符像以前一樣打印出來。 '-finput-charset = UTF-8'似乎沒有效果。 – 2012-02-12 04:45:56

+0

我認爲Clang只是不支持非ASCII輸入字符集。 [This thread](http://clang-developers.42468.n3.nabble.com/Supporting-finput-charset-fexec-charset-and-fwide-exec-charset-td3057650.html)意味着開始工作了僅在去年六月份。作爲一種解決方法,您可以使用通用字符名稱'\ uABCD',而不是將它們直接放在源代碼中,至少從Clang 3.0開始。 – 2012-02-12 05:07:49

相關問題