2014-01-05 2 views
3

Я написал этот код:Почему я получаю число вместо символа Unicode?

#include <iostream> 

int main() 
{ 
    std::wcout << '\u00E1' << std::endl; 
} 

Но it outputs 50081 when compiled with GCC 4.8.1.

Я, вероятно, что-то делаю неправильно, но я, конечно, не ожидал вывода числа. Что происходит?

+0

-1 Вы компилируете другой код – Abyx

+0

@Abyx: Ссылка исправлена ​​<3 –

+0

OK <3. Тогда -1 для не использования '-Wall -Werror' ('/W4/WX' в VC++) – Abyx

ответ

3

Я считаю, что это ошибка в g ++. Тип '\u00E1' - char, но g ++ рассматривает его как int. clang ++ получает это право.

Рассмотрим соответствующей программы (с перегруженной type_of функции для определения типа литералов):

#include <iostream> 

const char *type_of(char) { return "char"; } 
const char *type_of(int) { return "int"; } 

int main() 
{ 
    std::cout << "type_of('x') = " << type_of('x') << "\n"; 
    std::cout << "type_of('xy') = " << type_of('xy') << "\n";   // line 9 
    std::cout << "type_of('\u00E1') = " << type_of('\u00E1') << "\n"; // line 10 
    std::cout << "type_of('\u0100') = " << type_of('\u0100') << "\n"; // line 11 
} 

Когда я компилирую это с г ++ 4.7.2, я получаю эти предупреждения:

c.cpp:9:47: warning: multi-character character constant [-Wmultichar] 
c.cpp:10:52: warning: multi-character character constant [-Wmultichar] 
c.cpp:11:52: warning: multi-character character constant [-Wmultichar] 

и этот выход:

type_of('x') = char 
type_of('xy') = int 
type_of('á') = int 
type_of('Ā') = int 

С лязгом ++ 3.0, я получить только два предупреждения:

c.cpp:9:47: warning: multi-character character constant [-Wmultichar] 
    std::cout << "type_of('xy') = " << type_of('xy') << "\n"; 
              ^
c.cpp:11:52: warning: character unicode escape sequence too long for its type 
    std::cout << "type_of('\u0100') = " << type_of('\u0100') << "\n"; 

и этот выход:

type_of('x') = char 
type_of('xy') = int 
type_of('á') = char 
type_of('Ā') = char 

Характер буквальным '\u00E1' имеет только один кесарево обугленного-последовательность, которая случается быть универсального характера, имя по , поэтому он имеет тип char, но g ++ неправильно рассматривает его как многосимвольную константу типа int. clang ++ корректно трактует его как обычный символьный литерал типа char.

Значение такого символьного литерала, значение которого находится за пределами диапазона char, определено реализацией, но оно по-прежнему относится к типу char.

Поскольку вы пишете std::wcout, вы, вероятно, хотели широкую литеру: L'\u00E1', который имеет типа char_t, а не '\u00E1', который (если ваш компилятор обрабатывает его правильно) имеет типа int.

+0

+1: Gracias .... –

2

Это, кажется, ошибка компилятора.

В соответствии со стандартом (2.14.3/1) '\u00E1' представляет собой обычный литерой (он не имеет u, U или L префикс), который содержит один с-символ (который является универсальным -character-name), таким образом, он имеет тип char.

Таким образом, std::wcout << '\u00E1' следует использовать operator<<(char) и распечатать один символ.

Вместо этого он принимает, что универсального характера имя, преобразует его в UTF-8 закодированную последовательность и получает multicharacter буквальным '\ xc3 \ xÀ1', который является int со значением 50081:

'\u00E1' -> '\xC3\xA1' -> 50081 
+0

Не требует ли такое «2.14.3/5» такого преобразования? –

+0

@LightnessRacesinOrbit: Это все еще тип 'char'. –

+0

@ KeithThompson: Таким образом, преобразование происходит слишком поздно, чтобы эффективно создать более одного _c-char_ для '2.14.3/1', чтобы нанести удар? Я искренне прошу дважды проверить, прежде чем удалить свой ответ. –

Смежные вопросы