เครื่องหมายคำพูดเดี่ยวทำใน C ++ เมื่อใช้กับอักขระหลายตัวได้อย่างไร


279

ฉันอยากรู้เกี่ยวกับรหัสนี้:

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

1952805748ให้ฉันเอาท์พุทของ

คำถามของฉัน: เอาท์พุทที่อยู่ในหน่วยความจำหรืออะไร?


10
ให้ความสนใจว่ามูลค่าที่แท้จริงคือการดำเนินการกำหนดstackoverflow.com/questions/3960954/c-multicharacter-literal
FireAphis

คำตอบ:


283

มันเป็นตัวอักษรที่หลากหลาย 1952805748คือ0x74657374ซึ่งสลายตัวเป็น

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

แก้ไข:

มาตรฐาน C ++, §2.14.3 / 1 - ตัวอักษรตัวละคร

(... ) ตัวอักษรธรรมดาที่มีตัวอักษร c-char มากกว่าหนึ่งตัวเป็นตัวอักษรหลายตัว ตัวอักษรหลายตัวมีค่า int และการปรับใช้การพิมพ์


11
คุณไม่ได้พูดถึงว่านี่เป็นการใช้งานที่กำหนดไว้
Thomas Bonini

2
ฉันคิดว่าสิ่งที่สนุกที่สุดเกี่ยวกับคำจำกัดความนั้นsizeof(int)ก็คือการดำเนินการที่กำหนดไว้เช่นกัน ดังนั้นไม่เพียง แต่จะมีการกำหนดการใช้งานการจัดเก็บข้อมูลเท่านั้น แต่ความยาวสูงสุดของสิ่งเหล่านี้ก็เช่นกัน
bobobobo

74

ไม่มันไม่ใช่ที่อยู่ มันเป็นตัวละครมัลติไบต์ที่เรียกว่า

โดยทั่วไปแล้วมันคือค่า ASCII ของอักขระสี่ตัวที่รวมกัน

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

ดังนั้น 0x74657374 คือ 1952805748

แต่ก็อาจเป็น 0x74736574 ในคอมไพเลอร์อื่น ๆ ซีและ C ++ มาตรฐานทั้งสองบอกว่าคุ้มค่าของตัวอักษรสัญลักษณ์ที่มีการดำเนินงานที่กำหนดไว้ ดังนั้นโดยทั่วไปการใช้งานจึงไม่สนับสนุนอย่างยิ่ง


ความยาวของอักขระหลายไบต์ถูก จำกัด ไว้ที่ 4 ไบต์หรือไม่ คือมันเป็นตัวแทนของ int เขียนเป็นตัวละคร?
Giorgio

2
@Giorgio: มาตรฐานกล่าวเพียงว่ามันใช้งานได้โดยไม่มีรายละเอียดเพิ่มเติม ในทางปฏิบัติเนื่องจากintเป็น 4 ไบต์ในเครื่องส่วนใหญ่ฉันไม่คิดว่ามันสมเหตุสมผลที่จะใช้มากกว่า 4 ไบต์ ใช่มันตั้งใจที่จะเป็นวิธีที่สะดวกในการเขียนค่าคงที่บางส่วน แต่น่าเสียดายที่คอมไพเลอร์ที่แตกต่างกันได้ตีความมันแตกต่างกันไปดังนั้นรูปแบบการเข้ารหัสส่วนใหญ่ในปัจจุบันจึงไม่สนับสนุนการใช้งาน
chys

2
@chys: และความจริงที่ว่าการกำหนดใช้งานนั้นหมายถึงไม่จำเป็นต้องมีความสอดคล้องกัน คอมไพเลอร์ที่สอดคล้องกันสามารถให้ค่าตัวอักษรหลายตัวอักษรทั้งหมดเช่น 0 (แม้ว่าจะไม่เป็นมิตร)
Keith Thompson

2
เราต้องถามว่าทำไมคุณสมบัติบ้า ๆ บอ ๆ นี้จึงมีอยู่ในมาตรฐาน ดูเหมือนว่ากรณีการใช้งานที่หายากเช่นนี้จะถูกกำหนดไว้ในการใช้งานและสามารถทำได้ค่อนข้างชัดเจนโดยใช้การเลื่อนบิตแบบธรรมดาและหรือหากจำเป็น
Boann

1
@Boann ใช่ความรู้สึกของฉันอย่างแน่นอน แต่คุณสามารถใช้งานได้อย่างปลอดภัยในสวิตช์และอะไรก็ตามเนื่องจากการเปรียบเทียบโดยตรง==ควรตรวจสอบ
bobobobo

18

ตัวอักษรตัวอักษรธรรมดาที่มีมากกว่าหนึ่ง c-char เป็นตัวอักษรหลายตัว ตัวอักษรหลายตัวมีค่า int และการปรับใช้การพิมพ์

พฤติกรรมที่กำหนดไว้ในการนำไปปฏิบัติจะต้องมีการบันทึกไว้ในการปฏิบัติ ตัวอย่างเช่นใน gcc คุณสามารถค้นหาได้ที่นี่

คอมไพเลอร์ให้ค่าอักขระหลายตัวคงที่อักขระหนึ่งครั้งเลื่อนค่าก่อนหน้านี้ทิ้งตามจำนวนบิตต่ออักขระเป้าหมายจากนั้นหรือ-ing ในรูปแบบบิตของอักขระใหม่ที่ถูกตัดให้เป็นความกว้างของเป้าหมาย ตัวละคร รูปแบบบิตสุดท้ายจะได้รับประเภท int และดังนั้นจึงมีการลงนามโดยไม่คำนึงว่าตัวอักษรเดียวมีการลงนามหรือไม่

ตรวจสอบคำอธิบายในหน้านี้สำหรับรายละเอียดเพิ่มเติม


10

พวกมันแค่ints จริงๆ พวกมันถูกใช้อย่างกว้างขวางใน Core Audio API enum's เช่นในCoreAudioTypes.hไฟล์ส่วนหัว

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

มีเรื่องไร้สาระมากมายเกี่ยวกับเรื่องนี้ไม่ได้เป็น "แพลตฟอร์มอิสระ" แต่เมื่อคุณใช้ API ที่ทำขึ้นสำหรับแพลตฟอร์มเฉพาะใครสนใจเรื่องการพกพา การตรวจสอบความเท่าเทียมกันบนแพลตฟอร์มเดียวกันจะไม่ล้มเหลว ค่าเหล่านี้enumง่ายต่อการอ่านและจริง ๆ แล้วพวกเขามีตัวตนของพวกเขาในค่าของพวกเขาซึ่งเป็นสิ่งที่ดีงาม

สิ่งที่ฉันพยายามทำด้านล่างคือห่ออักขระหลายไบต์ตามตัวอักษรขึ้นมาเพื่อให้สามารถพิมพ์ได้ (บน Mac ใช้งานได้) สิ่งที่แปลกคือถ้าคุณไม่ใช้อักขระทั้งหมด 4 ตัวผลลัพธ์จะผิดด้านล่าง ..

#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
"การตรวจสอบความเท่าเทียมกันบนแพลตฟอร์มเดียวกันจะไม่ล้มเหลว" มันอาจจะ. อัปเกรดเป็น Visual Studio xyzแล้วกัดลิ้นของคุณ ห้องสมุดนี้มีการตัดสินใจที่น่ากลัว
Lightness Races ที่ Orbit

@LightnessRacesinOrbit "อัปเกรดเป็น Visual Studio xyz แล้วกัดลิ้นของคุณ" Core Audio API เป็น API ระบบเสียงของ OS X ดังนั้นนี่จึงไม่เกี่ยวข้อง
Jean-Michaël Celerier

5
@ Jean-MichaëlCelerier: สบายดี; อัปเกรด OSX Clang ของคุณและกัดลิ้นของคุณ ...
Lightness Races in Orbit

1

คุณลักษณะประเภทนี้ดีมากเมื่อคุณสร้างโปรแกรมแยกวิเคราะห์ พิจารณาสิ่งนี้:

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

รหัสนี้มีแนวโน้มที่จะทำงานได้กับ endianess ที่เฉพาะเจาะจงและอาจแตกต่างจากคอมไพเลอร์ที่แตกต่างกัน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.