Que font les guillemets simples en C ++ lorsqu’ils sont utilisés sur plusieurs caractères?

Je suis curieux de ce code:

cout << 'test'; // Note the single quotes. 

me donne une sortie de 1952805748 .

Ma question: la sortie est-elle une adresse en mémoire ou quelque chose?

C’est un littéral multi-caractères. 1952805748 est 0x74657374 , qui se décompose en

 0x74 -> 't' 0x65 -> 'e' 0x73 -> 's' 0x74 -> 't' 

Modifier:

Norme C ++, §2.14.3 / 1 – Littéraux de caractères

(…) Un littéral de caractère ordinaire qui contient plus d’un caractère c est un littéral à plusieurs caractères. Un littéral multi-caractères a un type int et une valeur définie par l’implémentation.

Non, ce n’est pas une adresse. C’est le soi-disant caractère multi-octets.

Généralement, ce sont les valeurs ASCII des quatre caractères combinées.

 't' == 0x74; 'e' == 0x65; 's' == 0x73; 't' == 0x74; 

Donc, 0x74657374 est 1952805748.

Mais il peut aussi être 0x74736574 sur un autre compilateur. Les normes C et C ++ affirment toutes deux que la valeur des caractères multi-octets est définie par l’implémentation . Donc, en général, son utilisation est fortement déconseillée.

Un littéral de caractère ordinaire contenant plus d’un caractère c est un littéral à plusieurs caractères. Un littéral multi-caractères a un type int et une valeur définie par l’implémentation.

Le comportement défini par l’implémentation doit être documenté par l’implémentation. par exemple dans gcc vous pouvez le trouver ici

Le compilateur évalue une constante de caractère à plusieurs caractères, un caractère à la fois, en décalant la valeur précédente du nombre de bits par caractère cible, puis en alignant le modèle de bit du nouveau caractère tronqué à la largeur d’une cible. personnage. Le dernier modèle de bit est de type int et est donc signé, que des caractères soient signés ou non.

Vérifiez l’explication dans cette page pour plus de détails

Ils sont vraiment juste int . Ils sont largement utilisés dans l’énumération de l’API Core Audio, par exemple, dans le fichier d’en-tête CoreAudioTypes.h ,

 enum { kAudioFormatLinearPCM = 'lpcm', kAudioFormatAC3 = 'ac-3', kAudioFormat60958AC3 = 'cac3', kAudioFormatAppleIMA4 = 'ima4', kAudioFormatMPEG4AAC = 'aac ', kAudioFormatMPEG4CELP = 'celp', } ; 

Il y a beaucoup de bavardage à propos de ceci ne pas être “indépendant de la plate-forme”, mais quand vous utilisez un api qui est fait pour une plate-forme spécifique, qui se soucie de la portabilité. Vérifier l’égalité sur la même plate-forme n’échouera jamais. Ces valeurs enum sont plus faciles à lire et contiennent en réalité leur identité dans leur valeur , ce qui est plutôt bien.

Ce que j’ai essayé de faire ci-dessous, c’est d’envelopper un littéral de caractères multi-octets pour pouvoir imprimer (sur Mac, cela fonctionne). La chose étrange est que si vous n’utilisez pas tous les 4 caractères, le résultat devient faux ci-dessous.

 #include  #define MASK(x,BYTEX) ((x&(0xff<<8*BYTEX))>>(8*BYTEX)) struct Multibyte { union{ int val ; char vals[4]; }; Multibyte() : val(0) { } Multibyte( int in ) { vals[0] = MASK(in,3); vals[1] = MASK(in,2); vals[2] = MASK(in,1); vals[3] = MASK(in,0); } char operator[]( int i ) { return val >> (3-i)*8 ; // works on mac //return val>>i*8 ; // might work on other systems } void println() { for( int i = 0 ; i < 4 ; i++ ) putc( vals[i], stdout ) ; puts( "" ) ; } } ; int main(int argc, const char * argv[]) { Multibyte( 'abcd' ).println() ; Multibyte( 'x097' ).println() ; Multibyte( '\"\\\'\'' ).println() ; Multibyte( '/*|' ).println() ; Multibyte( 'd' ).println() ; return 0; } 

Ce type de fonctionnalité est vraiment bon lorsque vous construisez des parsingurs. Considère ceci:

 byte* buffer = ...; if(*(int*)buffer == 'GET ') invoke_get_method(buffer+4); 

Ce code ne fonctionnera probablement que sur des endianess spécifiques et pourrait se retrouver sur différents compilateurs.