Was machen einfache Anführungszeichen in C ++, wenn sie für mehrere Zeichen verwendet werden?


279

Ich bin neugierig auf diesen Code:

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

gibt mir eine Ausgabe von 1952805748 .

Meine Frage: Ist die Ausgabe eine Adresse im Speicher oder so?


Antworten:


283

Es ist ein mehrstelliges Literal. 1952805748ist 0x74657374, das zerfällt als

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

Bearbeiten:

C ++ Standard, §2.14.3 / 1 - Zeichenliterale

(...) Ein gewöhnliches Zeichenliteral, das mehr als ein c-Zeichen enthält, ist ein Mehrzeichenliteral. Ein Multicharacter-Literal hat den Typ int und einen implementierungsdefinierten Wert.


11
Sie haben nicht erwähnt, dass dies eine definierte Implementierung ist.
Thomas Bonini

2
Ich nehme an, das Lustigste an dieser Definition ist, dass auch sizeof(int)die Implementierung definiert ist. Es wird also nicht nur die Implementierung der Speicherreihenfolge definiert, sondern auch deren maximale Länge.
Bobobobo

74

Nein, es ist keine Adresse. Es ist das sogenannte Multibyte-Zeichen.

In der Regel sind dies die ASCII-Werte der vier Zeichen zusammen.

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

0x74657374 ist also 1952805748.

Es kann aber auch 0x74736574 auf einem anderen Compiler sein. Die C- und C ++ - Standards besagen beide, dass der Wert von Multibyte-Zeichen durch die Implementierung definiert ist . Daher wird generell dringend von seiner Verwendung abgeraten.


Ist die Länge eines solchen Mehrbytezeichens auf 4 Byte beschränkt? Dh stellt es ein int dar, das als Zeichen geschrieben ist?
Giorgio

2
@Giorgio: Der Standard sagt nur, dass die Implementierung definiert ist, ohne weitere Details. In der Praxis inthalte ich es nicht für sinnvoll, mehr als 4 Bytes zu verwenden , da auf den meisten Computern 4 Bytes vorhanden sind. Ja, es sollte eine bequeme Möglichkeit sein, einige Konstanten zu schreiben, aber leider haben verschiedene Compiler sie unterschiedlich interpretiert, so dass heutzutage die meisten Codierungsstile von ihrer Verwendung abraten.
chys

2
@chys: Und die Tatsache, dass es implementierungsdefiniert ist, bedeutet, dass es nicht einmal konsistent sein muss. Ein konformer Compiler könnte beispielsweise allen Mehrzeichenliteralen den Wert 0 geben (obwohl dies unfreundlich wäre).
Keith Thompson

2
Man muss sich fragen, warum diese verrückte Funktion im Standard vorhanden ist. Es scheint ein so seltener Anwendungsfall zu sein, die Implementierung ist sowieso definiert und kann bei Bedarf ganz einfach mit gewöhnlichen Bitverschiebungen und / oder -änderungen durchgeführt werden.
Boann

1
@ Boann Ja , meine Gefühle genau. Aber Sie können es sicher in Schaltern und so weiter verwenden, als direkter Vergleich für ==sollte überprüfen
Bobobobo

18

Ein gewöhnliches Zeichenliteral, das mehr als ein c-Zeichen enthält, ist ein Mehrzeichenliteral. Ein Multicharacter-Literal hat den Typ int und einen implementierungsdefinierten Wert.

Implementierungsdefiniertes Verhalten muss von der Implementierung dokumentiert werden. Zum Beispiel in gcc finden Sie es hier

Der Compiler bewertet eine mehrstellige Zeichenkonstante jeweils für ein Zeichen, wobei der vorherige Wert um die Anzahl der Bits pro Zielzeichen verschoben und dann im Bitmuster des neuen Zeichens auf die Breite eines Ziels gekürzt wird Charakter. Das endgültige Bitmuster erhält den Typ int und ist daher signiert, unabhängig davon, ob einzelne Zeichen signiert sind oder nicht.

Weitere Informationen finden Sie in der Erklärung auf dieser Seite


10

Sie sind wirklich nur ints. Sie werden häufig in den Core Audio API-Enums verwendet, z. B. in der CoreAudioTypes.hHeader-Datei.

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

Es wird viel darüber geredet, dass dies nicht "plattformunabhängig" ist, aber wenn Sie eine API verwenden, die für eine bestimmte Plattform erstellt wurde, ist Portabilität wichtig. Die Überprüfung der Gleichheit auf derselben Plattform wird niemals fehlschlagen. Diese enumWerte sind leichter zu lesen und enthalten tatsächlich ihre Identität in ihrem Wert , was ziemlich nett ist.

Was ich unten versucht habe, ist ein Multibyte-Zeichenliteral einzuwickeln, damit es gedruckt werden kann (auf dem Mac funktioniert dies). Das Seltsame ist, wenn Sie nicht alle 4 Zeichen verbrauchen, wird das Ergebnis unten falsch.

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

6
"Die Überprüfung der Gleichheit auf derselben Plattform wird niemals fehlschlagen." Es könnte. Aktualisieren Sie auf Visual Studio xyz und beißen Sie sich auf die Zunge. Diese Bibliothek hat eine schreckliche Entscheidung getroffen.
Leichtigkeitsrennen im Orbit

@LightnessRacesinOrbit " Aktualisieren Sie auf Visual Studio xyz und beißen Sie sich auf die Zunge." Die Core Audio API ist die System Audio API von OS X, daher ist dies nicht relevant.
Jean-Michaël Celerier

5
@ Jean-MichaëlCelerier: Gut; Aktualisieren Sie Ihre OSX Clang-Version und beißen Sie sich auf die Zunge ...
Lightness Races in Orbit

1

Diese Art von Funktion ist wirklich gut, wenn Sie Parser erstellen. Bedenken Sie:

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

Dieser Code funktioniert wahrscheinlich nur für bestimmte Endianess und kann über verschiedene Compiler hinweg funktionieren

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.