2014-05-09 54 views
4

下面的代碼行給出了垃圾與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中的錯誤還是我錯過了一些東西。問候。

+0

這是一個罕見的問題,它可以並且應該合法地標記C++和C. – Deduplicator

+0

@Deduplicator C和C++看似普遍的一些庫函數確實在它們之間有一些差異。除非OP完全確定兩種語言的答案是相同的,並且有一個具體的原因是爲什麼單個語言標籤不夠用,我認爲OP僅僅將它標記爲C++是正確的。 – hvd

+0

@ hvd:我並不是暗示OP是粗魯的或者是錯誤的,只是在這種情況下C同樣適用。因此,我建議添加C.如果我給你不同的印象,我很抱歉。 – Deduplicator

回答

4

這是一個「錯誤」,雖然行爲是通過設計。寬字符串printf和scanf函數的初始Visual C++實現早於C中的標準化,並且在某些情況下,行爲會偏離C標準庫規範所要求的行爲。

在C標準庫說明書中,%s%c格式說明必須始終與一個char陣列或元件配對,並且提供了一種wchar_t陣列或元件時,必須使用在l長度改性劑。

在這些函數(documentation)的Visual C++實現中,%s%c格式說明符需要「自然」寬度的相應參數。對於窄字符串printf和scanf函數,需要指針或元素,而對於寬字符串函數,則需要wchar_t指針或元素。要傳遞「其他」寬度的字符串,可以使用%S%C格式說明符。或者,可以使用長度修飾符hl來明確指定字符串參數是窄字符串還是寬字符串。

除了其他優點之外,這些函數的Visual C++實現使得可以通過the _TCHAR mappings in <tchar.h>輕鬆遷移舊代碼以使用Unicode字符串。不幸的是,標準化的內容與已經在Visual C++實現中實現的標準不同(我不熟悉這裏的歷史;可能標準化與另一個實現相匹配)。

+0

UCS-2在移動到UTF-16之前; UTF-8也是Unicode。至少同樣不幸的是,他們轉而使用UCS-2而不是UTF-8。 – Deduplicator

+0

它是在那個時候發明的,但這並沒有改變這個事實,即它是不幸的恕我直言。另外,它並沒有改變只假裝UTF-16是unicode的事實至少是誤導性的。 – Deduplicator

0

%s和%S具有不同的含義:

S:當與printf的功能使用時,指定一個單字節或多字節的字符串;當與wprintf函數一起使用時,指定一個寬字符的字符串。字符顯示到第一個空字符或直到達到精度值。 S:與printf函數一起使用時,指定一個寬字符的字符串;當與wprintf函數一起使用時,指定一個單字節或多字節字符串。字符顯示到第一個空字符或直到達到精度值。

這就是爲什麼

swprintf(buf, L"Value is %S", "abcd"); 

顯示正確的值。

MSDN鏈接是here

+0

這並不能解釋OP的觀察結果,儘管你至少得到了一半的解釋。 – Deduplicator

+0

這個答案應該指出,'%s'的這種解釋並不符合C99標準。 –

0

「abcd」是一個很窄的字符串,因爲您省略了'L'。 swprintf()期望所有的%s字符串輸入都很寬。

3

Microsoft實現的寬printfscanf功能不符合標準的,因此你會得到不同的結果在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重新定義了這些轉換說明符(cs),以期在與寬泛函數一起使用時使用UTF-16。