operaciones - ¿Cuándo empezaron los compiladores de C++ a considerar más de dos dígitos hexadecimales en cadenas de caracteres literales?
leer cadena de caracteres en c (6)
Estos son literales de caracteres anchos.
char foo[] = "/x00ABEcho";
Podría ser mejor.
Aquí hay algo de información, no gcc, pero todavía parece aplicar.
Este enlace incluye la línea importante:
Especificar
/xnn
en un literal de cadena wchar_t es equivalente a especificar/x00nn
Esto también puede ser útil.
http://www.gnu.org/s/hello/manual/libc/Extended-Char-Intro.html#Extended-Char-Intro
Tengo una cadena literal (generada) en C ++ que puede contener caracteres que deben escaparse usando la notación /x
. Por ejemplo:
char foo[] = "/xABEcho";
Sin embargo, g ++ (versión 4.1.2 si importa) emite un error:
test.cpp:1: error: hex escape sequence out of range
El compilador parece estar considerando los caracteres Ec
como parte del número hexadecimal anterior (porque parecen dígitos hexadecimales). Como un número hexadecimal de cuatro dígitos no cabe en un char
, se char
un error. Obviamente, para una cadena ancha literal L"/xABEcho"
el primer carácter sería U + ABEC, seguido de L"ho"
.
Parece que esto ha cambiado en algún momento en las últimas dos décadas y nunca me di cuenta. Estoy casi seguro de que los compiladores de C antiguos solo considerarían dos dígitos hexadecimales después de /x
, y no buscarían más.
Puedo pensar en una solución para esto:
char foo[] = "/xAB""Echo";
pero eso es un poco feo Así que tengo tres preguntas:
¿Cuándo cambió esto?
¿Por qué el compilador no acepta solo escapes hexadecimales de 2 dígitos para literales de cadena ancha?
¿Hay una solución que sea menos incómoda que la anterior?
Estoy bastante seguro de que C ++ siempre ha sido así. En cualquier caso, CHAR_BIT
puede ser mayor que 8, en cuyo caso ''/xABE''
o ''/xABEc''
podrían ser válidos.
GCC sólo está siguiendo el estándar . #877 : "Cada secuencia [...] de escape hexadecimal es la secuencia más larga de caracteres que puede constituir la secuencia de escape".
He encontrado respuestas a mis preguntas:
C ++ siempre ha sido así (verifiqué en la 3ª edición de Stroustrup, no tenía ninguna anterior). La primera edición de K&R no mencionó
/x
en absoluto (los únicos escapes de caracteres disponibles en ese momento eran octales). La 2ª edición de K&R declara:''/xhh''
donde hh es uno o más dígitos hexadecimales (0 ... 9, a ... f, A ... F).
por lo que parece que este comportamiento ha existido desde ANSI C.
Si bien es posible que el compilador solo acepte> 2 caracteres para literales de cadena amplia, esto complicaría innecesariamente la gramática.
De hecho, hay una solución menos incómoda:
char foo[] = "/u00ABEcho";
El escape
/u
acepta cuatro dígitos hexadecimales siempre.
Actualización : el uso de /u
no es del todo aplicable en todas las situaciones porque la mayoría de los caracteres ASCII no están permitidos (por alguna razón) para especificarse usando /u
. Aquí hay un fragmento de GCC:
/* The standard permits $, @ and ` to be specified as UCNs. We use
hex escapes so that this also works with EBCDIC hosts. */
else if ((result < 0xa0
&& (result != 0x24 && result != 0x40 && result != 0x60))
|| (result & 0x80000000)
|| (result >= 0xD800 && result <= 0xDFFF))
{
cpp_error (pfile, CPP_DL_ERROR,
"%.*s is not a valid universal character",
(int) (str - base), base);
result = 1;
}
Resolví esto especificando el siguiente carácter con / xnn también. Desafortunadamente, tiene que usar esto mientras haya caracteres en el rango [a..f]. ex. "/ xnneceg" se reemplaza por "/ xnn / x65 / x63 / x65g"
También me encontré con este problema. Descubrí que podía agregar un espacio al final del segundo dígito hexadecimal y luego deshacerme del espacio siguiendo el espacio con un retroceso ''/ b''. No exactamente deseable pero parecía funcionar.
"Julius C / xE6sar el conquistador de la frana / xE7 / bais"