J'ai une chaîne littérale (générée) en C++ pouvant contenir des caractères à échapper à l'aide de la \x
notation. Par exemple:
char foo[] = "\xABEcho";
Cependant, g ++ (version 4.1.2 si cela compte) jette une erreur:
test.cpp:1: error: hex escape sequence out of range
Le compilateur semble envisager de considérer les caractères Ec
dans le cadre du numéro hexagonal précédent (car ils ressemblent à des chiffres hexagonaux). Étant donné qu'un numéro hexagonal à quatre chiffres ne correspond pas à un char
, une erreur est soulevée. Évidemment pour un large littéral à chaîne L"\xABEcho"
Le premier personnage serait U + Abec, suivi de L"ho"
.
Il semble que cela a changé de temps au cours des deux dernières décennies et je n'ai jamais remarqué. Je suis presque certain que les anciens compilateurs C ne considèrent que deux chiffres hex après \x
, et ne pas regarder plus loin.
Je peux penser à une solution de contournement pour cela:
char foo[] = "\xAB""Echo";
mais c'est un peu moche. Donc, j'ai trois questions:
Quand cela a-t-il changé?
Pourquoi le compilateur n'accepte-t-il que> Hex à 2 chiffres s'échappe pour des littéraux stricts à deux chiffres?
Y a-t-il une solution de contournement moins gênant que ce qui précède?
GCC est seulement suivant la norme . # 877 : "Chaque séquence d'évacuation hexadécimale [...] est la plus longue séquence de caractères pouvant constituer la séquence d'échappement."
J'ai trouvé des réponses à mes questions:
C++ a toujours été de cette façon (vérifié STROSTRUP 3RD Edition, n'en avait pas plus tôt). K & R 1ST Edition n'a pas mentionné \x
du tout (le seul caractère échappe disponible à cette époque était octal). K & R 2nd Edition déclare:
'\xhh'
où HH est un ou plusieurs chiffres hexadécimaux (0 ... 9, un ... F, un ... F).
il semble donc que ce comportement existe depuis ANSI C.
Bien qu'il soit possible que le compilateur n'accepte que> 2 caractères pour des littéraux à large string, cela compliquerait inutilement la grammaire.
Il y a en effet une solution de contournement moins maladroite:
char foo[] = "\u00ABEcho";
Les \u
Escape accepte quatre chiffres hexagonales toujours.
Mise à jour: l'utilisation de \u
n'est pas tout à fait applicable dans toutes les situations car la plupart ASCII caractères sont (pour une raison quelconque) non autorisée à être spécifiée à l'aide de \u
. Voici un extrait 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;
}
J'ai résolu ceci en spécifiant le caractère suivant avec\xnn aussi. Malheureusement, vous devez l'utiliser aussi longtemps qu'il existe de la gamme [A..f]. ex. "\ xnEceau" est remplacé par "\ xnn\x65\x63\x65g"
Je suis sûr que C++ a toujours été de cette façon. Dans tous les cas, CHAR_BIT
peut être supérieur à 8, auquel cas '\xABE'
ou '\xABEc'
pourrait être valide.