Apa yang dilakukan tanda kutip tunggal dalam C ++ ketika digunakan pada banyak karakter?

279

Saya ingin tahu tentang kode ini:

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

memberi saya output 1952805748.

Pertanyaan saya: Apakah output alamat dalam memori atau sesuatu?

Kesadaran nyata
sumber
10
Perhatikan bahwa nilai sebenarnya adalah implementasi yang didefinisikan stackoverflow.com/questions/3960954/c-multicharacter-literal
FireAphis

Jawaban:

283

Ini adalah multi-karakter literal. 1952805748adalah 0x74657374, yang terurai menjadi

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

Edit:

Standar C ++, §2.14.3 / 1 - Literal karakter

(...) Huruf karakter biasa yang berisi lebih dari satu c-char adalah multicharacter literal. Multicharacter literal memiliki tipe int dan nilai yang didefinisikan implementasi.

K-ballo
sumber
11
Anda tidak menyebutkan bahwa ini adalah implementasi yang ditentukan.
Thomas Bonini
2
Saya kira hal paling lucu tentang definisi itu sizeof(int)adalah implementasi didefinisikan juga. Jadi tidak hanya implementasi urutan penyimpanan yang ditentukan, tetapi panjang maksimumnya juga.
bobobobo
74

Tidak, ini bukan alamat. Itu yang disebut karakter multibyte.

Biasanya, ini adalah nilai ASCII dari keempat karakter yang digabungkan.

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

Jadi 0x74657374 adalah 1952805748.

Tetapi bisa juga 0x74736574 pada beberapa kompiler lain. Standar C dan C ++ keduanya mengatakan nilai karakter multibyte adalah implementasi yang didefinisikan . Jadi umumnya penggunaannya sangat tidak dianjurkan.

chys
sumber
Apakah panjang karakter multi-byte dibatasi hingga 4 byte? Yaitu apakah itu mewakili int yang ditulis sebagai karakter?
Giorgio
2
@Iorgio: Standar hanya mengatakan implementasi itu ditentukan, tanpa rincian lebih lanjut. Dalam prakteknya, karena int4 byte pada kebanyakan mesin, saya pikir tidak masuk akal untuk menggunakan lebih dari 4 byte. Ya, itu dimaksudkan sebagai cara yang nyaman untuk menulis beberapa konstanta, tetapi sayangnya kompiler yang berbeda telah menafsirkannya secara berbeda, jadi saat ini sebagian besar gaya pengkodean mencegah penggunaannya.
chys
2
@chys: Dan fakta bahwa itu adalah implementasi yang ditentukan berarti itu bahkan tidak diperlukan untuk konsisten. Compiler yang menyesuaikan bisa memberikan semua literalitik multicharacter nilai 0, misalnya (meskipun itu tidak ramah).
Keith Thompson
2
Kita harus bertanya mengapa fitur gila ini ada dalam standar. Sepertinya kasus penggunaan yang jarang terjadi, adalah implementasi yang didefinisikan pula, dan dapat dilakukan dengan cukup jelas dengan bit shifting dan or'ing biasa jika diperlukan.
Boann
1
@Boann Ya , sentimen saya persis. Tetapi Anda dapat menggunakannya dengan aman di sakelar dan yang lainnya, karena perbandingan langsung ==harus diperiksa
bobobobo
18

Literal karakter biasa yang berisi lebih dari satu c-char adalah multicharacter literal. Multicharacter literal memiliki tipe int dan nilai yang didefinisikan implementasi.

Perilaku yang ditentukan implementasi harus didokumentasikan oleh implementasi. misalnya di gcc Anda dapat menemukannya di sini

Compiler menilai karakter multi-karakter yang konstan pada satu karakter pada suatu waktu, menggeser nilai sebelumnya yang ditinggalkan oleh jumlah bit per karakter target, dan kemudian memasukkan pola bit karakter baru yang dipotong ke lebar target. karakter. Pola bit terakhir diberikan tipe int, dan karenanya ditandatangani, terlepas dari apakah karakter tunggal ditandatangani atau tidak.

Periksa penjelasannya di halaman ini untuk detail lebih lanjut

Mouna Cheikhna
sumber
10

Mereka benar-benar hanya ints. Mereka digunakan secara luas di Core Audio API enum misalnya, dalam CoreAudioTypes.hfile header,

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

Ada banyak obrolan tentang ini tidak menjadi "platform independen", tetapi ketika Anda menggunakan api yang dibuat untuk platform tertentu, yang peduli tentang portabilitas. Memeriksa kesetaraan pada platform yang sama tidak akan pernah gagal. Ini enum'd nilai lebih mudah dibaca dan mereka benar-benar berisi identitas mereka di nilai mereka , yang cukup bagus.

Apa yang saya coba lakukan di bawah ini adalah membungkus karakter multibyte literal sehingga dapat dicetak (pada Mac ini berfungsi). Yang aneh adalah, jika Anda tidak menggunakan semua 4 karakter, hasilnya menjadi salah di bawah ini ..

#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;
}
bobobobo
sumber
6
"Memeriksa kesetaraan pada platform yang sama tidak akan pernah gagal." Itu mungkin. Tingkatkan ke Visual Studio xyz dan gigit lidah Anda. Perpustakaan ini telah membuat keputusan yang mengerikan .
Lightness Races di Orbit
@LightnessRacesinOrbit "Tingkatkan ke Visual Studio xyz dan gigit lidah Anda." Core Audio API adalah API audio sistem OS X jadi ini tidak relevan.
Jean-Michaël Celerier
5
@ Jean-MichaëlCelerier: Baik; tingkatkan versi OSX Anda Dentang dan gigit lidah Anda ...
Lightness Races in Orbit
1

Fitur semacam ini sangat bagus ketika Anda membuat parser. Pertimbangkan ini:

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

Kode ini kemungkinan hanya akan bekerja pada endianess tertentu dan mungkin menembus berbagai kompiler

Ayende Rahien
sumber