Usando Unicode no código-fonte C ++

Qual é a codificação padrão do código fonte do C ++? O padrão C ++ ainda diz algo sobre isso? Posso escrever fonte C ++ em Unicode?

Por exemplo, posso usar caracteres não ASCII, como caracteres chineses, nos comentários? Em caso afirmativo, o Unicode completo é permitido ou apenas um subconjunto do Unicode? (por exemplo, essa primeira página de 16 bits ou o que for chamado.)

Além disso, posso usar Unicode para strings? Por exemplo:

Wstring str=L"Strange chars: â Țđ ě €€"; 

A codificação em C ++ é um pouco complicada. Aqui está o meu entendimento sobre isso.

Toda implementação deve suportar caracteres do conjunto básico de caracteres de origem . Estes incluem caracteres comuns listados em §2.2 / 1 (§2.3 / 1 em C ++ 11). Esses caracteres devem caber em um char . Além disso, as implementações têm que suportar uma maneira de nomear outros caracteres usando um caminho chamado universal-character-names e se parecer com \uffff ou \Uffffffff e pode ser usado para se referir a caracteres Unicode. Um subconjunto deles é utilizável em identificadores (listados no Anexo E).

Tudo isso é legal, mas o mapeamento de caracteres no arquivo, para caracteres de origem (usados ​​no tempo de compilation) é definido pela implementação. Isso constitui a codificação usada. Aqui está o que diz literalmente (versão C ++ 98):

Os caracteres do arquivo de origem físico são mapeados, de uma maneira definida pela implementação, para o conjunto de caracteres de origem básico (introduzindo caracteres de nova linha para indicadores de fim de linha), se necessário. As seqüências Trigraph (2.3) são substituídas por representações internas correspondentes de um único caractere. Qualquer caractere de arquivo de origem que não esteja no conjunto de caracteres de origem básico (2.2) é substituído pelo nome de caractere universal que designa esse caractere. (Uma implementação pode usar qualquer codificação interna, desde que um caractere estendido real encontrado no arquivo de origem e o mesmo caractere estendido expressado no arquivo de origem como um nome de caractere universal (isto é, usando a notação \ uXXXX) sejam manipulados equivalentemente.)

Para o gcc, você pode alterá-lo usando a opção -finput-charset=charset . Além disso, você pode alterar o caractere de execução usado para representar valores em tempo de execução. A opção apropriada para isso é -fexec-charset=charset para char (o padrão é utf-8 ) e -fwide-exec-charset=charset (cujo padrão é utf-16 ou utf-32 dependendo do tamanho de wchar_t ) .

O padrão C ++ não diz nada sobre codificação de arquivo de código-fonte, tanto quanto eu sei.

A codificação usual é (ou costumava ser) ASCII de 7 bits – alguns compiladores (os da Borland, por exemplo) recusavam caracteres ASCII que usavam o bit mais alto. Não há motivos técnicos para que caracteres Unicode não possam ser usados, se seu compilador e editor os aceitarem – a maioria das ferramentas modernas baseadas em Linux, e muitos dos melhores editores baseados em Windows, manipulam a codificação UTF-8 sem problemas, embora eu Não tenho certeza se o compilador da Microsoft irá.

EDIT: Parece que os compiladores da Microsoft aceitarão arquivos codificados em Unicode, mas às vezes também produzirão erros em ASCII de 8 bits:

 warning C4819: The file contains a character that cannot be represented in the current code page (932). Save the file in Unicode format to prevent data loss. 

Além do post do litb, o MSVC ++ também suporta o Unicode. Eu entendo que obtém a codificação Unicode da lista de materiais. Ele definitivamente suporta código como int (*♫)(); ou const std::set ∅; Se você realmente gosta de ofuscação de código:

 typedef void ‼; // Also known as \u203C class ooɟ { operator ‼() {} }; 

Há duas questões em jogo aqui. A primeira é quais caracteres são permitidos no código C ++ (e comentários), como nomes de variables. A segunda é quais caracteres são permitidos em strings e literais de string.

Como observado, os compiladores C ++ devem suportar um conjunto de caracteres baseado em ASCII muito restrito para os caracteres permitidos no código e nos comentários. Na prática, esse conjunto de caracteres não funcionou muito bem com alguns conjuntos de caracteres europeus (e especialmente com alguns teclados europeus que não tinham alguns caracteres – como colchetes – disponíveis), de modo que o conceito de digraphs e trigraphs era introduzido. Muitos compiladores aceitam mais do que esse conjunto de caracteres neste momento, mas não há garantia.

Quanto às cadeias de caracteres e literais de string, o C ++ tem o conceito de um caractere amplo e uma cadeia de caracteres ampla. No entanto, a codificação para esse conjunto de caracteres é indefinida. Na prática, é quase sempre Unicode, mas não acho que haja garantia aqui. Os caracteres literais de caracteres largos parecem L “string literal” e podem ser atribuídos a std :: wstring.


O C ++ 11 adicionou suporte explícito para strings Unicode e literais string, codificados como UTF-8, UTF-16 big endian, UTF-16 little endian, UTF-32 big endian e UTF-32 little endian.

Para codificar em strings, acho que você deve usar a notação \ u , por exemplo:

 std::wstring str = L"\u20AC"; // Euro character 

Também é importante notar que caracteres largos em C ++ não são realmente seqüências Unicode como tal. Eles são apenas cordas de caracteres maiores, geralmente 16, mas às vezes 32 bits. Isso é implementação-definida, no entanto, IIRC você pode ter um 8-bit wchar_t Você não tem garantia real quanto à codificação neles, então se você está tentando fazer algo como processamento de texto, você provavelmente vai querer um typedef para o mais tipo inteiro adequado à sua entidade Unicode.

C ++ 1x tem suporte unicode adicional na forma de literais de string de codificação UTF-8 ( u8"text" ), e tipos de dados UTF-16 e UTF-32 ( char16_t e char32_t ) assim como constantes de string correspondentes ( u"text" e U"text" ). A codificação em caracteres especificados sem as \uxxxx ou \Uxxxxxxxx ainda é definida pela implementação (embora não haja suporte de codificação para tipos de cadeias complexas fora dos literais)

Neste contexto, se você receber o aviso C4819 do MSVC ++, apenas altere a codificação do arquivo de origem para “UTF-8 com Bom”.

O GCC 4.1 não suporta isso, mas o GCC 4.4 tem, e a última versão do Qt usa o GCC 4.4, então use “UTF-8 com Bom” como codificação do arquivo de origem.

AFAIK Não é padronizado, pois você pode colocar qualquer tipo de caractere em strings largos. Você só precisa verificar se o seu compilador está configurado para o código-fonte Unicode para que ele funcione corretamente.