Cosa fanno le virgolette singole in C ++ quando vengono utilizzate su più caratteri?


Risposte:


283

È un letterale multi-personaggio. 1952805748è 0x74657374, che si decompone come

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

Modificare:

Standard C ++, §2.14.3 / 1 - Letterali dei caratteri

(...) Un letterale carattere ordinario che contiene più di un c-char è un letterale multicaratterico. Un letterale multicharacter ha tipo int e valore definito dall'implementazione.


11
Non hai detto che si tratta di un'implementazione definita.
Thomas Bonini,

2
Suppongo che la cosa più divertente di quella definizione sia che sizeof(int)sia definita anche l'implementazione. Quindi non solo viene definita l'implementazione dell'ordine di archiviazione, ma anche la lunghezza massima di questi.
Bobobobo,

74

No, non è un indirizzo. È il cosiddetto personaggio multibyte.

In genere, sono i valori ASCII dei quattro caratteri combinati.

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

Quindi 0x74657374 è 1952805748.

Ma può anche essere 0x74736574 su qualche altro compilatore. Gli standard C e C ++ affermano entrambi che il valore dei caratteri multibyte è definito dall'implementazione . Quindi generalmente il suo uso è fortemente scoraggiato.


La lunghezza di un tale carattere multi-byte è limitata a 4 byte? Vale a dire rappresenta un int scritto come personaggi?
Giorgio,

2
@Giorgio: lo standard dice solo che è stata definita l'implementazione, senza ulteriori dettagli. In pratica, dato che intsono 4 byte sulla maggior parte delle macchine, non penso che abbia senso usare più di 4 byte. Sì, doveva essere un modo conveniente per scrivere alcune costanti, ma sfortunatamente compilatori diversi l'hanno interpretato in modo diverso, quindi oggigiorno la maggior parte degli stili di codifica ne scoraggia l'uso.
Chys,

2
@chys: E il fatto che sia definito dall'implementazione significa che non è nemmeno necessario che sia coerente. Un compilatore conforme potrebbe dare a tutti i letterali multicaratteri il valore 0, ad esempio (anche se sarebbe ostile).
Keith Thompson,

2
Bisogna chiedersi perché questa caratteristica pazza esiste nello standard. Sembra un caso d'uso così raro, l'implementazione è definita in ogni caso e può essere eseguita in modo abbastanza chiaro con il normale spostamento dei bit e o se necessario.
Boann,

1
@Boann , i miei sentimenti esattamente. Ma puoi tranquillamente usarlo negli switch e quant'altro, come il confronto diretto per ==dovrebbe verificare
bobobobo

18

Un letterale personaggio ordinario che contiene più di un c-char è un letterale multicaratterico. Un letterale multicharacter ha tipo int e valore definito dall'implementazione.

Il comportamento definito dall'implementazione deve essere documentato dall'implementazione. ad esempio in gcc puoi trovarlo qui

Il compilatore valuta una costante di carattere multi-carattere un carattere alla volta, spostando il valore precedente lasciato dal numero di bit per carattere di destinazione e quindi inserendo il modello di bit del nuovo carattere troncato alla larghezza di una destinazione carattere. Il bit-pattern finale è di tipo int, ed è quindi firmato, indipendentemente dal fatto che i singoli caratteri siano firmati o meno.

Controlla la spiegazione in questa pagina per maggiori dettagli


10

Sono davvero solo ints. Sono ampiamente utilizzati nell'enum API Core Audio, ad esempio nel CoreAudioTypes.hfile header,

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

Ci sono molte chiacchiere sul fatto che questo non sia "indipendente dalla piattaforma", ma quando si utilizza un API creato per una piattaforma specifica, a cui interessa la portabilità. Il controllo dell'uguaglianza sulla stessa piattaforma non fallirà mai. Questi enumvalori sono più facili da leggere e in realtà contengono la loro identità nel loro valore , il che è piuttosto carino.

Quello che ho provato a fare di seguito è avvolgere letteralmente un carattere multibyte in modo che possa essere stampato (su Mac funziona). La cosa strana è che se non si utilizzano tutti e 4 i caratteri, il risultato diventa errato di seguito.

#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
"Il controllo dell'uguaglianza sulla stessa piattaforma non fallirà mai." Potrebbe. Passa a Visual Studio xyz e morditi la lingua. Questa biblioteca ha preso una decisione terribile .
Razze di leggerezza in orbita

@LightnessRacesinOrbit "Esegui l'upgrade a Visual Studio xyz e morditi la lingua." L'API audio principale è l'API audio di sistema di OS X, quindi non è rilevante.
Jean-Michaël Celerier,

5
@ Jean-MichaëlCelerier: Bene; aggiorna la tua versione di OSX Clang e mordi la lingua ...
Razze di leggerezza in orbita

1

Questo tipo di funzionalità è davvero utile quando si creano parser. Considera questo:

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

Questo codice probabilmente funzionerà solo su endianess specifici e potrebbe essere suddiviso tra diversi compilatori

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.