Quand les compilateurs C ++ ont-ils commencé à considérer plus de deux chiffres hexadécimaux dans le caractère littéral des chaînes?

J’ai une chaîne littérale (générée) en C ++ qui peut contenir des caractères qui doivent être échappés en utilisant la notation \x . Par exemple:

 char foo[] = "\xABEcho"; 

Cependant, g ++ (version 4.1.2 si elle compte) lance une erreur:

 test.cpp:1: error: hex escape sequence out of range 

Le compilateur semble considérer les caractères Ec comme faisant partie du nombre hexadécimal précédent (car ils ressemblent à des chiffres hexadécimaux). Comme un nombre hexadécimal à quatre chiffres ne tient pas dans un caractère, une erreur est générée. De toute évidence, pour un littéral de chaîne large L"\xABEcho" le premier caractère serait U + ABEC, suivi de L"ho" .

Il semble que cela ait changé au cours des deux dernières décennies et je n’ai jamais remarqué. Je suis presque certain que les anciens compilateurs C ne prendraient en compte que deux chiffres hexadécimaux après \x , et ne chercheraient pas plus loin.

Je peux penser à une solution de contournement pour cela:

 char foo[] = "\xAB""Echo"; 

mais c’est un peu moche. J’ai donc trois questions:

  • Quand est-ce que cela a changé?

  • Pourquoi le compilateur n’accepte-t-il que les caractères hexadécimaux à deux chiffres pour les littéraux de chaîne larges?

  • Existe-t-il une solution de rechange moins délicate que celle ci-dessus?

GCC ne suit que la norme . # 877 : “Chaque séquence d’échappement 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é comme ça (vérifié Stroustrup 3ème édition, n’a pas eu plus tôt). K & R 1ère édition ne mentionne pas du tout \x (les seules échappées de caractères disponibles à cette époque étaient octales). K & R 2ème édition déclare:

     '\xhh' 

    hh est un ou plusieurs chiffres hexadécimaux (0 … 9, a … f, A … 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 les littéraux de chaîne larges, cela compliquerait inutilement la grammaire.

  • Il existe en effet une solution de contournement moins délicate:

     char foo[] = "\u00ABEcho"; 

    Le \u échapper accepte toujours quatre chiffres hexadécimaux.

Mise à jour : L’utilisation de \u n’est pas tout à fait applicable dans toutes les situations, car la plupart des caractères ASCII ne sont pas autorisés (pour une raison quelconque) avec \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 ce problème en spécifiant le caractère suivant avec \ xnn également. Malheureusement, vous devez l’utiliser aussi longtemps qu’il y a des caractères dans la plage [a..f]. ex. “\ xnneceg” est remplacé par “\ xnn \ x65 \ x63 \ x65g”

Je suis presque sûr que C ++ a toujours été ainsi. Dans tous les cas, CHAR_BIT peut être supérieur à 8, auquel cas '\xABE' ou '\xABEc' pourrait être valide.

Ce sont des littéraux de caractères larges.

 char foo[] = "\x00ABEcho"; 

Peut-être mieux.

Voici quelques informations, pas gcc, mais semble toujours s’appliquer.

http://publib.boulder.ibm.com/infocenter/iadthelp/v7r0/index.jsp?topic=/com.ibm.etools.iseries.pgmgd.doc/cpprog624.htm

Ce lien comprend la ligne importante:

Spécifier \xnn dans un littéral de chaîne wchar_t équivaut à spécifier \x00nn

Cela peut aussi être utile.

http://www.gnu.org/s/hello/manual/libc/Extended-Char-Intro.html#Extended-Char-Intro

J’ai aussi rencontré ce problème. J’ai trouvé que je pouvais append un espace à la fin du deuxième chiffre hexadécimal et ensuite éliminer l’espace en suivant l’espace avec un retour arrière ‘\ b’. Pas exactement souhaitable, mais cela semblait fonctionner.

“Jules C \ xE6sar le conquérant de la frana \ xE7 \ bais”