Unicode vs Multi-byte

Я действительно запутался в этом unicode и многобайтовой вещи.

Скажем, что я компилирую свою программу в Unicode (но в конечном итоге, я хочу, чтобы решение не зависело от используемого набора символов).

1) Будут ли все "char" интерпретироваться как широкие символы?

2) Если у меня есть простой оператор printf, т.е. printf ( "Hello World\n" ); без символьных строк, могу ли я просто оставить его без использования _tprintf и _T ( "..." )? Если инструкция printf содержит строку символов, тогда я должен использовать _tprintf и _T ( "..." ), то есть _tprintf ( "Hello% s\n", name);

3) Если у меня есть текстовый файл (сохраненный в формате по умолчанию, т.е. без изменения используемого набора символов по умолчанию), который я хочу прочитать в буфере, могу ли я использовать char вместо TCHAR? Особенно, если я читаю его по символу, то есть путем увеличения символьного указателя?

Спасибо.

С уважением, Rayne

Ответы

Ответ 1

Во-первых, если вы компилируете с помощью UNICODE/_UNICODE и не собираетесь нацеливать другие платформы, вы можете не использовать бизнес TCHAR и использовать WCHAR (или wchar_t) и W функции везде.

1) Будут ли все "char" интерпретироваться как широкие символы?

char в C - по определению - 1 байт. (Это технически не мешает ему быть "широким символом" на платформах, где wchar_t также является 1 байтом, но учитывая, что вы используете MSVC и ориентируетесь на платформы Windows, это не произойдет.)

Итак, для практических целей ответ на этот вопрос: no.

2) Если у меня есть простой оператор printf, т.е. printf ( "Hello World\n" ); без символьных строк, могу ли я просто оставить его без использования _tprintf и _T ( "..." )? Если инструкция printf содержит строку символов, тогда я должен использовать _tprintf и _T ( "..." ), то есть _tprintf ( "Hello% s\n", name);

Если вы печатаете строковые литералы ASCII, вы можете продолжать использовать printf.

Если вы печатаете произвольные строки, которые могут лежать вне диапазона ASCII, вы должны использовать _tprintf (или wprintf).

3) Если у меня есть текстовый файл (сохраненный в формате по умолчанию, т.е. без изменения используемого набора символов по умолчанию), который я хочу прочитать в буфере, могу ли я использовать char вместо TCHAR? Особенно, если я читаю его по символу, то есть путем увеличения символьного указателя?

Что такое "формат по умолчанию"?

Когда вы читаете во внешнем файле, сначала должны прочитать первые несколько байтов, чтобы проверить спецификацию UTF-16 или UTF-8, а затем основывать свои решения на этом.

Ответ 2

1) Будут ли все "char" интерпретироваться как широкие символы?

Нет. Но все TCHAR будут интерпретироваться как wchar_t s

Рассмотрим, как winnt.h, вероятно, укажет следующее:

#ifdef UNICODE
 typedef WCHAR TCHAR;
#else
 typedef CHAR TCHAR;
#endif

Когда вы вызываете SomeApi(), он будет привязан к SomeApiA(char *arg) или SomeApiW(wchar_t *arg). (аргументы в действительности будут TCHAR, но вы получите точку).

Таким образом, ваш исходный код будет "независимым" в том смысле, что он может быть скомпилирован либо в "ANSI", либо в версии Widechar. Для этого вам нужно использовать TCHAR вместо примитивных типов.

2) Если у меня есть простой оператор printf, т.е. printf ( "Hello World\n" ); без символьных строк, могу ли я просто оставить его без использования _tprintf и _T ( "..." )? Если инструкция printf содержит строку символов, тогда я должен использовать _tprintf и _T ( "..." ), то есть _tprintf ( "Hello% s\n", name);

Я не знаю семейства tprintf, кроме как я могу предположить, что они работают так же, как и описанные выше. То есть tprintf принимает TCHAR как аргумент и зависит от параметра UNICODE либо рассматривает их как char или wchar_t s.

3) Если у меня есть текстовый файл (сохраненный в формате по умолчанию, т.е. без изменения используемого набора символов по умолчанию), который я хочу прочитать в буфере, могу ли я использовать char вместо TCHAR? Особенно, если я читаю его по символу, то есть путем увеличения символьного указателя?

Какой символ, кодирующий содержимое файла, полностью зависит от него и не имеет ничего общего с TCHAR. TCHAR относятся к именам файлов и таким образом, что вы используете в вызовах API Win32.

Ответ 3

Скажем, что я компилирую свою программу в Unicode (но в конечном итоге, я хочу, чтобы решение не зависело от используемого набора символов).

Это будет зависеть от вашего языка - как от языка программирования, нежели от разговорной речи. Что вы подразумеваете под "компиляцией моей программы в Unicode"?

  • Будет ли все "char" интерпретироваться как широкие символы?

    • Это зависит от языка и выбранных опций. Например, Java использует 16-битные символы (сохраняя UTF-16 или UCS-2 - когда-то давно это был UCS-2, но я предполагаю, что это теперь UTF-16). В C вам придется работать довольно сложно, чтобы базовый тип "char" интерпретировался как что-то отличное от 8-битного количества - по крайней мере, на компиляторах на базе Unix.
  • Если у меня есть простой оператор printf, т.е. printf ( "Hello World\n" ); без символьных строк, могу ли я просто оставить его без использования _tprintf и _T ( "..." )? Если инструкция printf содержит строку символов, тогда я должен использовать _tprintf и _T ( "..." ), то есть _tprintf ( "Hello% s\n", name);

    • Для этого требуется некоторое понимание платформы, над которой вы работаете, поскольку она далеко не стандартная. Я подозреваю, что это MSVC... что затрудняет для меня быть авторитетным, поскольку я не использую MSVC. Однако стандарт ISO C99 (который не поддерживается MSVC) предоставляет такие функции, как fwprintf() для печати строк с широкими символами. Если вам нужна информация о вашем конкретном компиляторе, пометьте свой вопрос правильной информацией.
  • Если у меня есть текстовый файл (сохраненный в формате по умолчанию, т.е. без изменения используемого набора символов по умолчанию), который я хочу прочитать в буфере, могу ли я использовать char вместо TCHAR? Особенно, если я читаю его по символу, то есть путем увеличения символьного указателя?

    • Опять же, TCHAR не является стандартным - он очень специфичен для MSVC. В стандарте C поток файлов приобретает "ориентацию" (широко ориентированную или байт-ориентированную), когда вы применяете к ней соответствующие функции. Он остается в этой ориентации до тех пор, пока он не будет закрыт (или снова открыт с помощью freopen()).