Printf, wprintf,% s,% S,% ls, char * и wchar *: Ошибки, не объявленные предупреждением компилятора? - программирование
Подтвердить что ты не робот

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

Итак: кажется, что как wprintf, так и printf могут корректно печатать как 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
4b9b3361

Ответ 1

Я подозреваю, что GCC (mingw) имеет собственный код для отключения проверок широких функций printf в Windows. Это связано с тем, что собственная реализация Microsoft (MSVCRT) ошибочна и имеет %s и %ls назад для широких функций printf; так как GCC не может быть уверен, что вы будете связываться с MS-сломанной реализацией или исправленной, наименее навязчивая вещь, которую он может сделать, это просто отключить предупреждение.

Ответ 2

Формат определяет значение: "% s" говорит, что следующая строка представляет собой узкую строку ( "ascii" и обычно 8 бит на символ). "% S" означает широкую строку char. Смешивание двух даст "поведение undefined", которое включает печать мусора, только один символ или ничего.

Один символ печатается, потому что широкие символы - это, например, 16 бит в ширину, а первый байт отличен от нуля, за ним следует нулевой байт → конец строки в узких строках. Это зависит от байтового порядка, на машине с большим энтузиастом вы не получите никакой строки, потому что первый байт равен нулю, а следующий байт содержит ненулевое значение.

Ответ 3

По крайней мере, в Visual С++:   printf (и другие функции ACSII):       % s представляет собой строку ASCII       % S - строка в Юникоде   wprintf (и другие функции Unicode):       % s - строка Unicode       % S - строка ASCII

Что касается предупреждений компилятора, printf использует список аргументов переменных, причем только первый аргумент может быть проверен типом. Компилятор не предназначен для синтаксического анализа строки форматирования и типа проверки соответствующих параметров. В случаях таких функций, как printf, это зависит от программиста

Ответ 4

%S, похоже, соответствует Single Unix Specification v2 и также является частью текущего (2008) спецификация POSIX.

Эквивалентные спецификаторы формата C99 соответствуют %S и %ls.

Ответ 5

Для s: При использовании с функциями printf задает однобайтную или многобайтную строку символов; при использовании с функциями wprintf задает широкоформатную строку. Символы отображаются до первого нулевого символа или до достижения значения точности.

Для S: При использовании с функциями printf задает широкосимвольную строку; при использовании с функциями wprintf задает однобайтную или многобайтную строку символов. Символы отображаются до первого нулевого символа или до достижения значения точности.

В Unix-подобной платформе s и S имеют то же значение, что и платформа Windows.

Ссылка: https://msdn.microsoft.com/en-us/library/hf4y5e3w.aspx