web-dev-qa-db-fra.com

Comment ajouter correctement des échappements hexadécimaux dans un littéral de chaîne?

Lorsque vous avez une chaîne en C, vous pouvez ajouter du code hexadécimal direct à l'intérieur.

char str[] = "abcde"; // 'a', 'b', 'c', 'd', 'e', 0x00
char str2[] = "abc\x12\x34"; // 'a', 'b', 'c', 0x12, 0x34, 0x00

Les deux exemples ont 6 octets en mémoire. Maintenant, le problème existe si vous voulez ajouter de la valeur [a-fA-F0-9] après l'entrée hexadécimale.

//I want: 'a', 'b', 'c', 0x12, 'e', 0x00
//Error, hex is too big because last e is treated as part of hex thus becoming 0x12e
char problem[] = "abc\x12e";

La solution possible est de remplacer après définition.

//This will work, bad idea
char solution[6] = "abcde";
solution[3] = 0x12;

Cela peut fonctionner, mais il échouera si vous le mettez en tant que const.

//This will not work
const char solution[6] = "abcde";
solution[3] = 0x12; //Compilation error!

Comment insérer correctement e après \x12 sans déclencher d'erreur?


Pourquoi je demande? Lorsque vous souhaitez créer une chaîne TF-8 constante, vous devez utiliser des valeurs hexadécimales de caractères si elle est supérieure à ASCII peut contenir.

44
tilz0R

Utilisez 3 chiffres octaux:

char problem[] = "abc\022e";

ou divisez votre chaîne:

char problem[] = "abc\x12" "e";

Pourquoi ces travaux:

  • Contrairement aux échappements hexadécimaux, la norme définit 3 chiffres comme montant maximum pour l'échappement octal.

    6.4.4.4 Constantes de caractères

    ...

    octal-escape-sequence:
        \ octal-digit
        \ octal-digit octal-digit
        \ octal-digit octal-digit octal-digit
    

    ...

    hexadecimal-escape-sequence:
        \x hexadecimal-digit
        hexadecimal-escape-sequence hexadecimal-digit
    
  • La concaténation littérale de chaîne est définie comme une phase de traduction ultérieure à la conversion de caractère d'échappement littéral.

    5.1.1.2 Phases de traduction

    ...

    1. Chaque membre du jeu de caractères source et séquence d'échappement dans les constantes de caractères et les littéraux de chaîne est converti en membre correspondant du jeu de caractères d'exécution; s'il n'y a pas de membre correspondant, il est converti en un membre défini par l'implémentation autre que le caractère null (large). 8)

    2. Les jetons littéraux de chaîne adjacents sont concaténés.

53
user694733

Étant donné que les littéraux de chaîne sont concaténés au début du processus de compilation, mais après la conversion de caractères d'échappement, vous pouvez simplement utiliser:

char problem[] = "abc\x12" "e";

bien que vous préfériez une séparation complète pour plus de lisibilité:

char problem[] = "abc" "\x12" "e";

Pour les juristes de langue parmi nous, cela est couvert par C11 5.1.1.2 Translation phases (c'est moi qui souligne):

  1. Chaque membre du jeu de caractères source et séquence d'échappement dans les constantes de caractères et littéraux de chaîne est converti en membre correspondant du jeu de caractères d'exécution; s'il n'y a pas de membre correspondant, il est converti en un membre défini par l'implémentation autre que le caractère null (large).

  2. Les jetons littéraux de chaîne adjacents sont concaténés.

19
paxdiablo

Pourquoi je demande? Lorsque vous souhaitez créer une chaîne UTF-8 comme constante, vous devez utiliser des valeurs hexadécimales de caractères supérieures à ASCII peut contenir.

Et bien non. Vous n'avez pas devez. Depuis C11, vous pouvez préfixer votre constante de chaîne avec u8, qui indique au compilateur que le littéral de caractère est en UTF-8.

char solution[] = u8"no need to use hex-codes á駵";

(La même chose est également prise en charge par C++ 11)

4
Damon