web-dev-qa-db-ja.com

printf、wprintf、%s、%S、%ls、char *、およびwchar *:コンパイラの警告によって通知されないエラー?

私は次のコードを試しました:

wprintf(L"1 %s\n","some string"); //Good
wprintf(L"2 %s\n",L"some string"); //Not good -> print only first character of the string
printf("3 %s\n","some string"); //Good
//printf("4 %s\n",L"some string"); //Doesn't compile
printf("\n");
wprintf(L"1 %S\n","some string"); //Not good -> print some funny stuff
wprintf(L"2 %S\n",L"some string"); //Good
//printf("3 %S\n","some string"); //Doesn't compile
printf("4 %S\n",L"some string");  //Good

そして、私は次の出力を取得します:

1 some string
2 s
3 some string

1 g1 %s

2 some string
4 some string

そのため、wprintfprintfの両方がchar *とwchar *の両方を正しく印刷できるようですが、正確な指定子が使用されている場合のみです。 間違った指定子を使用すると、コンパイルエラー(警告もありません!)が表示されず、誤った動作が発生する可能性があります。同じ動作を経験しますか?

注:これはWindowsでテストされ、MinGWおよびg ++ 4.7.2でコンパイルされました(gccは後で確認します)

編集:私も%lsを試しました(結果はコメントにあります)

printf("\n");
wprintf(L"1 %ls\n","some string"); //Not good -> print funny stuff
wprintf(L"2 %ls\n",L"some string"); //Good
// printf("3 %ls\n","some string"); //Doesn't compile
printf("4 %ls\n",L"some string");  //Good
21
Antonio

GCC(mingw)には、Windowsのワイドprintf関数のチェックを無効にするカスタムコードがあると思われます。これは、Microsoft独自の実装(MSVCRT)がひどく間違っているであり、%sおよび%ls後方ワイドprintf関数の場合; GCCは、MSの壊れた実装と修正された実装のどちらをリンクするのかを確信できないため、できる限り控えめなことは警告を遮断することです。

23
R..

形式指定子は重要です。「%s」は、次の文字列が狭い文字列(「ascii」、通常は1文字あたり8ビット)であることを示します。 「%S」はワイド文字列を意味します。この2つを混ぜると、「未定義の動作」が発生します。これには、ごみの印刷、1文字のみ、または何も含まれません。

ワイド文字は、たとえば16ビット幅であり、最初のバイトがゼロ以外であり、その後にナロー文字列でゼロバイト->文字列の終わりが続くため、1文字が出力されます。これは、バイトオーダーに依存します。「ビッグエンディアン」マシンでは、最初のバイトがゼロで、次のバイトにゼロ以外の値が含まれるため、文字列はまったく得られません。

17
Mats Petersson

少なくともVisual C++の場合:printf(および他のACSII関数):%sはASCII string%SはUnicode文字列wprintf(および他のUnicode関数):%sはUnicode文字列です% SはASCII文字列

コンパイラの警告がない限り、printfは可変引数リストを使用し、最初の引数のみが型チェックされます。コンパイラは、フォーマット文字列を解析し、一致するパラメータを型チェックするようには設計されていません。 printfのような関数の場合、それはプログラマ次第です

4
Steve R

s:の場合printf関数で使用する場合、シングルバイトまたはマルチバイトの文字列を指定します。 wprintf関数で使用する場合、ワイド文字ストリングを指定します。文字は、最初のヌル文字まで、または精度値に達するまで表示されます。

Sの場合:printf関数で使用する場合、ワイド文字列を指定します。 wprintf関数とともに使用する場合、シングルバイトまたはマルチバイトの文字列を指定します。文字は、最初のヌル文字まで、または精度値に達するまで表示されます。

Unixライクなプラットフォームでは、sとSはWindowsプラットフォームと同じ意味を持ちます。

参照: https://msdn.Microsoft.com/en-us/library/hf4y5e3w.aspx

3
user3581075

%SThe Single Unix Specification v2 に準拠しているようで、現在(2008)の一部でもあります POSIX仕様

同等のC99準拠のフォーマット指定子は%sおよび%ls

0
David Foerster