下面的代碼行給出了垃圾與Visual Studio 2010:的swprintf()窄弦
swprintf(buf, L"Value is %s", "abcd");
然而,同樣的代碼工作正常,在Linux上。
通過試用,我可以在Visual Studio下使用%S代替%s。
swprintf(buf, L"Value is %S", "abcd");
我想知道這是Visual Studio 2010中的錯誤還是我錯過了一些東西。問候。
下面的代碼行給出了垃圾與Visual Studio 2010:的swprintf()窄弦
swprintf(buf, L"Value is %s", "abcd");
然而,同樣的代碼工作正常,在Linux上。
通過試用,我可以在Visual Studio下使用%S代替%s。
swprintf(buf, L"Value is %S", "abcd");
我想知道這是Visual Studio 2010中的錯誤還是我錯過了一些東西。問候。
這是一個「錯誤」,雖然行爲是通過設計。寬字符串printf和scanf函數的初始Visual C++實現早於C中的標準化,並且在某些情況下,行爲會偏離C標準庫規範所要求的行爲。
在C標準庫說明書中,%s
或%c
格式說明必須始終與一個char
陣列或元件配對,並且提供了一種wchar_t
陣列或元件時,必須使用在l
長度改性劑。
在這些函數(documentation)的Visual C++實現中,%s
和%c
格式說明符需要「自然」寬度的相應參數。對於窄字符串printf和scanf函數,需要指針或元素,而對於寬字符串函數,則需要wchar_t
指針或元素。要傳遞「其他」寬度的字符串,可以使用%S
和%C
格式說明符。或者,可以使用長度修飾符h
和l
來明確指定字符串參數是窄字符串還是寬字符串。
除了其他優點之外,這些函數的Visual C++實現使得可以通過the _TCHAR
mappings in <tchar.h>
輕鬆遷移舊代碼以使用Unicode字符串。不幸的是,標準化的內容與已經在Visual C++實現中實現的標準不同(我不熟悉這裏的歷史;可能標準化與另一個實現相匹配)。
UCS-2在移動到UTF-16之前; UTF-8也是Unicode。至少同樣不幸的是,他們轉而使用UCS-2而不是UTF-8。 – Deduplicator
它是在那個時候發明的,但這並沒有改變這個事實,即它是不幸的恕我直言。另外,它並沒有改變只假裝UTF-16是unicode的事實至少是誤導性的。 – Deduplicator
%s和%S具有不同的含義:
S:當與printf的功能使用時,指定一個單字節或多字節的字符串;當與wprintf函數一起使用時,指定一個寬字符的字符串。字符顯示到第一個空字符或直到達到精度值。 S:與printf函數一起使用時,指定一個寬字符的字符串;當與wprintf函數一起使用時,指定一個單字節或多字節字符串。字符顯示到第一個空字符或直到達到精度值。
這就是爲什麼
swprintf(buf, L"Value is %S", "abcd");
顯示正確的值。
MSDN鏈接是here。
這並不能解釋OP的觀察結果,儘管你至少得到了一半的解釋。 – Deduplicator
這個答案應該指出,'%s'的這種解釋並不符合C99標準。 –
「abcd」是一個很窄的字符串,因爲您省略了'L'。 swprintf()期望所有的%s字符串輸入都很寬。
Microsoft實現的寬printf
和scanf
功能不符合標準的,因此你會得到不同的結果在Linux(符合標準的)和Windows(打破)。當它們與使用printf
的C,S和Z類型的字符,和的C和S型的字符的行爲:
The link Matt posted in his answer指向在該行爲不端一個MSDN頁面提示和wprintf函數,都是Microsoft的擴展,並且不是ANSI兼容的。 Visual C++不支持F型字符。
強調我的。順便說一句:在這裏,ANSI意味着所有的C標準,並擴展C++標準。
具體問題是MS重新定義了這些轉換說明符(c
s
),以期在與寬泛函數一起使用時使用UTF-16。
這是一個罕見的問題,它可以並且應該合法地標記C++和C. – Deduplicator
@Deduplicator C和C++看似普遍的一些庫函數確實在它們之間有一些差異。除非OP完全確定兩種語言的答案是相同的,並且有一個具體的原因是爲什麼單個語言標籤不夠用,我認爲OP僅僅將它標記爲C++是正確的。 – hvd
@ hvd:我並不是暗示OP是粗魯的或者是錯誤的,只是在這種情況下C同樣適用。因此,我建議添加C.如果我給你不同的印象,我很抱歉。 – Deduplicator