web-dev-qa-db-fra.com

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

Je suis curieux de connaître 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?

277
lucidreality

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

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

Edit:

norme C++, §2.14.3/1 - Littéraux de caractères

(...) Un littéral de caractère ordinaire contenant plus d'un c-char est un littéral à plusieurs caractères. Un littéral multicaractère a une valeur de type int et une valeur définie par implémentation.

282
K-ballo

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

En règle générale, il s’agit des valeurs ASCII) des quatre caractères combinés.

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

Donc 0x74657374 est 1952805748.

Mais cela peut aussi être 0x74736574 sur un autre compilateur. Les normes C et C++ indiquent toutes deux que la valeur des caractères multi-octets est définition d'implémentation. En règle générale, son utilisation est fortement déconseillée.

73
chys

Un littéral de caractère ordinaire contenant plus d'un c-char est un littéral à plusieurs caractères. Un littéral multicaractère a une valeur de type int et une valeur définie par 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 valorise une constante de caractère multi-caractère, un caractère à la fois, en décalant la valeur précédente laissée par le nombre de bits par caractère cible, puis en reprenant le motif de bits du nouveau caractère tronqué à la largeur d'une cible. personnage. Le modèle de bits final est de type int et est donc signé, que les caractères soient signés ou non.

Consultez l'explication dans cette page pour plus de détails

17
Mouna Cheikhna

Ils sont vraiment juste ints. Ils sont largement utilisés dans l'énum de l'API Core Audio, par exemple, dans le CoreAudioTypes.h En tête de fichier,

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

Il y a beaucoup de discussions sur le fait que cela n'est pas "indépendant de la plate-forme", mais lorsque vous utilisez une API qui est faite 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 enum 'd valeurs sont plus faciles à lire et contiennent réellement leur identité dans leur valeur, ce qui est plutôt joli.

Ce que j’ai essayé de faire ci-dessous, c’est d’envelopper un littéral multi-octets pour qu’il puisse être imprimé (sur Mac, cela fonctionne). Ce qui est étrange, c'est que si vous n'utilisez pas les 4 caractères, le résultat devient faux en dessous.

#include <stdio.h>

#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;
}
10
bobobobo

Ce type de fonctionnalité est vraiment utile lorsque vous construisez des analyseurs syntaxiques. Considère ceci:

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

Ce code ne fonctionnera probablement que sur une endianess spécifique et pourrait traverser différents compilateurs

1
Ayende Rahien