Я знаю, что только положительные символьные значения ASCII гарантированы кроссплатформенной поддержкой.
В Visual Studio 2015 я могу сделать:
cout << '\xBA';
И это печатает:
║
Когда я примеряю это http://ideone.com Я ничего не печатаю.
Если я попытаюсь напечатать это, используя буквенный символ:
cout << '║';
Visual Studio выдает предупреждение:
предупреждение C4566: символ, представленный универсальным символьным именем ‘\ u2551’, не может быть представлен в текущей кодовой странице (1252)
А потом печатает:
?
Когда эта команда запущена на http://ideone.com Я получил:
14849425
Я прочитал это wchar
Это может обеспечить кроссплатформенный подход к этому. Это правда? Или мне просто не повезло в расширенном ASCII?
Во-первых, ваш исходный файл имеет свою собственную кодировку. Ваш компилятор должен уметь читать эту кодировку (возможно, с помощью флагов / настроек).
С простой строкой, компилятор может делать то, что он хочет, но он должен давать const char[]
, Обычно компилятор сохраняет исходную кодировку когда это может, поэтому строка, хранящаяся в вашей программе, будет иметь кодировку вашего входного файла. Бывают случаи, когда компилятор выполняет преобразование, например, если ваш файл имеет формат UTF-16 (вы не можете поместить символы UTF-16 в char
с).
Когда вы используете ‘\ xBA’, вы пишете необработанный символ и выбираете себе кодировку, поэтому кодировка компилятора отсутствует.
Когда вы используете '║'
, тип '║'
не обязательно char
, Если символ не представлен в виде одного байта в наборе символов компилятора, его тип будет int
, В случае Visual Studio с исходным файлом Windows-1252, '║'
не подходит, поэтому будет иметь тип int
и напечатан как таковой cout <<
,
Вы можете принудительно кодировать префиксы для строковых литералов. u8""
заставит UTF-8, u""
UTF-16 и U""
UTF-32. Обратите внимание, что L""
префикс даст вам широкий символ wchar_t
строка, но это все еще зависит от реализации. Широкие символы в Windows — это UCS-2 (2 байта на символ), но UTF-32 (4 байта на символ) в Linux.
Печать в консоль зависит только от типа переменной. cout <<
перегружен всеми распространенными типами, поэтому то, что он делает, зависит от типа. cout <<
будет обычно кормить char
строки как есть для консоли (на самом деле stdin), и wcout <<
будет обычно кормить wchar_t
Строки как есть. Другие комбинации могут иметь преобразования или интерпретации (например, кормление int
). Струны UTF-8 char
струны, так cout <<
всегда должен кормить их правильно.
Далее идет сама консоль. Консоль — это совершенно независимая часть программного обеспечения. Вы передаете ему несколько байтов, он отображает их. Вас не волнует ни одна ваша программа. Он использует свою собственную кодировку и пытается распечатать байты, которые вы передали, используя эту кодировку.
Кодировка консоли по умолчанию в Windows — это кодовая страница 850 (не всегда так). В вашем случае ваш файл — CP 1252, а ваша консоль — CP 850, поэтому вы не можете печатать '║'
напрямую (CP 1252 не содержит '║'
), но вы можете использовать необработанный символ. Вы можете изменить кодировку консоли в Windows с помощью SetConsoleCP()
,
В linux кодировкой по умолчанию является UTF-8, что более удобно, поскольку поддерживает весь диапазон Unicode. Ideone использует Linux, поэтому он будет использовать UTF-8. Обратите внимание, что есть добавленный слой HTTP и HTML, но они также используют UTF-8 для этого.
Здесь есть две отдельные концепции.
Первый из них является языковым стандартом, который в Microsoft-ese часто называют «кодовой страницей». Локаль определяет, какие визуальные символы представлены какой байтовой последовательностью. В вашем первом примере, в какой бы локали ваша программа ни выполнялась, она показывает символ «║» в ответ на байт 0xBA.
Другие локали или кодовые страницы будут отображать разные символы для одних и тех же байтов. Многие локали являются многобайтовыми локализацией, где для отображения одного символа может потребоваться несколько байтов. Например, в локали UTF-8 для отображения одного и того же символа display требуется три байта: 0xE2 0x95 0x91.
Второе понятие здесь — это один из набора символов исходного кода, который исходит из локали, в которой редактируется исходный код, до его компиляции. Когда вы вводите символ in в исходном коде, он может быть представлен, я полагаю, либо как символ 0xBA, либо, возможно, 0xE2 0x95 0x91, если ваш редактор использует локаль UTF-8. Компилятор, когда он читает исходный код, просто видит фактическую последовательность байтов. Все уменьшается до байтов.
К счастью, все ключевые слова C ++ используют US-ASCII, поэтому не имеет значения, какой набор символов используется для написания кода C ++. Пока вы не начнете использовать нелатинские символы. В результате выдается предупреждение компилятора, информирующее вас в основном о том, что вы используете то, что может работать, а может и не работать, в зависимости от конечной локали, в которой работает результирующая программа.