Размеры кодировки символов Unicode C/C++ и форматы по умолчанию

Я только что понял, что (благодаря моему университетскому курсу) многие вещи, которые, как мне казалось, я знал о юникоде, были неверны. Таким образом, я начал читать и закреплять свои знания, и сразу же возникли следующие сомнения, поигравшись с простой программой «Hello world» на C++ в MSVC2012:

#include <iostream>
#include <string.h>
using namespace std;

int main(void) {

    char arr1[] = "I am a nice boy"; // Is this stored as UTF-8 (multi-byte) or ASCII?
    char arr[] = "I'm a nice èboi"; // All characters should be ASCII except the 'è' one, which encoding is used for this?
    cout << strlen(arr); // Returns 15 as ASCII, why?

    // If I choose "multi-byte character set" in my VS project configuration instead of "unicode", what does this mean and what
    // will this affect?

    char arr2[] = "I'm a niße boy"; // And what encoding is it used here?
    cout << strlen(arr2); // Returns 1514, what does this mean?

    // If UTF-32 usually use 4 bytes to encode a character (even if they're not needed), how can a unicode code point like U+FFFF
    // (FFFF hexadecimal is 65535 in decimal) represent any possible unicode character if the maximum is FFFF ? (http://inamidst.com/stuff/unidata/)

    return 0;
}

Вышеупомянутое было скомпилировано с «многобайтовым набором символов», но, поскольку многобайтность — это тип кодировки Unicode, я думаю (?), Даже это не ясно.

Может ли кто-нибудь помочь мне с четкими объяснениями по приведенным выше вопросам?


person Marco A.    schedule 15.02.2014    source источник
comment
Дело не в Юникоде, а в VS2012. Если вы не понимаете, используете ли вы вообще Unicode, то вопросов по Unicode вообще нет.   -  person bmargulies    schedule 15.02.2014
comment
Затем отредактируйте вопрос и добавьте тег, если вы так думаете.   -  person Marco A.    schedule 15.02.2014
comment
Мистер Кернин, я не нахожу ваш тон вежливым. Это зависит от вас, чтобы задать вопрос, на который можно ответить. если вы знаете, находится ли ваш исходный файл в UTF-8 или какой-либо кодовой странице, отличной от юникода, отредактируйте свой вопрос. Если вы этого не сделаете, отредактируйте свой вопрос или, что еще лучше, узнайте, а затем отредактируйте свой вопрос.   -  person bmargulies    schedule 15.02.2014
comment
Во-первых, я не нашел ваш тон вежливым. Давайте оба устроимся, пожалуйста. Извините, если я написал неправильные вещи, это потому, что я запутался, а не потому, что пытаюсь донести свою точку зрения. Я отредактировал вопрос с тегом vs2012 и свойствами, которые я установил   -  person Marco A.    schedule 15.02.2014
comment
Я думаю, что ваш код выдаст ошибку для строки номер 8 cout ‹‹ strlen(arr); // Возвращает 15 в виде ASCII, почему? потому что здесь впервые использовано значение arr undefined.   -  person Shravan40    schedule 15.02.2014
comment
прочитайте это: utf8everywhere.org. Обещай быть бесценным.   -  person Pavel Radzivilovsky    schedule 17.02.2014


Ответы (3)


    char arr1[] = "I am a nice boy"; // Is this stored as UTF-8 (multi-byte) or ASCII?

Это хранится в кодировке выполнения компилятора. Компилятор выбирает, что это такое, и должен это документировать. GCC позволяет вам установить кодировку выполнения с помощью флага -fexec-charset=charset, но я думаю, что по умолчанию используется UTF-8, MSVC использует машинную «кодировку для приложений, отличных от Unicode», настроенную в настройках системного языка (которая никогда не может быть UTF-8), и clang безоговорочно использует UTF-8.

char arr[] = "I'm a nice èboi"; // All characters should be ASCII except the 'è' one, which encoding is used for this?
cout << strlen(arr); // Returns 15 as ASCII, why?

Кодировка выполнения компилятора на самом деле вообще не должна быть совместима с ASCII. Например, это может быть EBDIC.

strlen(arr) возвращает 15, потому что строковый литерал, закодированный с использованием набора символов выполнения компилятора, имеет длину 15 байт. Поскольку строковый литерал имеет длину 15 символов, это, вероятно, означает, что кодировка выполнения компилятора использовала один байт для каждого из этих символов, включая 'è'. (И поскольку UTF-8 не может закодировать эту строку всего в 15 байтах, это окончательно указывает на то, что ваш компилятор не использует UTF-8 в качестве кодировки выполнения компилятора.)

char arr2[] = "I'm a niße boy"; // And what encoding is it used here?
cout << strlen(arr2); // Returns 1514, what does this mean?

Кодировка не меняется в зависимости от содержимого строки. Компилятор всегда будет использовать кодировку выполнения. Я предполагаю, что «1514» является опечаткой, а strlen(arr2) на самом деле возвращает 14, потому что в этой строке 14 символов, и поскольку более ранняя строка, похоже, также использовала один байт на символ.

Если я выберу «многобайтовый набор символов» в конфигурации моего проекта VS вместо «Unicode», что это значит и на что это повлияет?

Этот параметр не имеет ничего общего с кодировками, используемыми компилятором. Он просто устанавливает макросы в заголовках Microsoft для разных вещей. TCHAR, все макросы, которые выбирают между функциями *W и *A и т. д.

На самом деле вполне возможно написать программу, используя многобайтовые строки символов, когда вы включаете «юникод», и можно также использовать юникод, когда вы включаете «многобайтовый набор символов».

Если UTF-32 обычно использует 4 байта для кодирования символа (даже если они не нужны), как кодовая точка юникода, такая как U + FFFF (шестнадцатеричный FFFF равен 65535 в десятичном), представляет любой возможный символ юникода, если максимум FFFF ? (http://inamidst.com/stuff/unidata/)

Этот вопрос не имеет смысла. Возможно, если перефразировать...

person bames53    schedule 15.02.2014
comment
Вы ответили на все, кроме последнего, на который Реми ответил правильно. Я все еще присуждаю вам баллы, но ставлю +1 к его ответу. Спасибо! - person Marco A.; 18.02.2014

char содержит 8-битное значение в C++, независимо от всего остального. Итак, эти переменные содержат последовательности байтов. Если они вообще в Юникоде, а их может и не быть, то они, таким образом, в UTF-8.

Акцентированные символы в наборе Latin-1 (например, è) имеют два представления в Unicode: составное и разложенное. Составные версии представляют собой один символ, разложенные - два. Вы можете просмотреть такие ресурсы, как http://www.fileformat.info/info/unicode/char/e8/index.htm; он скажет вам, что символ, который вы разместили в своем вопросе, составлен, а в UTF-8 это 0xC3 0xA8 (c3a8) (два байта).

Также возможно, что вы компилируете в ACP для Latin1, а не в Unicode, и в этом случае все эти символы будут иметь длину в один байт.

Ваш стрлен 1514 года мне непонятен; Я хочу задаться вопросом, не инициализируется ли char[] = "xxxx" конечным нулем, но я не помню ни того, ни другого. Вместо этого вы можете попробовать изменить их на char* и увидеть, что вы получите другой ответ.

person bmargulies    schedule 15.02.2014
comment
strlen из 1514 может быть связано с тем, что после первого вызова cout OP не ставит новую строку, поэтому реальная длина строки составляет всего 14. - person Banex; 15.02.2014
comment
Банекс прав, глупый я. Извините .. спасибо за остальную часть ответа и извините, если я был груб в начале. - person Marco A.; 15.02.2014
comment
char не обязательно будет 8-битным - person David Heffernan; 18.02.2014
comment
Это на его компиляторе, нет? - person bmargulies; 18.02.2014

Если UTF-32 обычно использует 4 байта для кодирования символа (даже если они не нужны), как кодовая точка юникода, такая как U + FFFF (шестнадцатеричный FFFF равен 65535 в десятичном), представляет любой возможный символ юникода, если максимум FFFF ? (http://inamidst.com/stuff/unidata/)

Ваш источник устарел. Unicode был ограничен максимальной кодовой точкой U + FFFF еще в первые дни, когда UCS-2 был единственной кодировкой Unicode, но Unicode перерос это ограничение несколько лет назад. UTF (UTF-8, UTF-16, UTF-32) были созданы для замены UCS-2 и расширения ограничения, которое в настоящее время составляет кодовую точку U+10FFFF (самая высокая кодовая точка, которую может кодировать UTF-16).

person Remy Lebeau    schedule 17.02.2014
comment
Спасибо! Это именно то, что я имел в виду - person Marco A.; 18.02.2014