Các trích dẫn đơn làm gì trong C ++ khi được sử dụng trên nhiều ký tự?


Câu trả lời:


283

Đó là một nghĩa đen đa nhân vật. 19528057480x74657374, mà phân hủy là

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

Biên tập:

Tiêu chuẩn C ++, §2,14.3 / 1 - Ký tự chữ

(...) Một ký tự thông thường có chứa nhiều hơn một c-char là một nghĩa đen đa chủng loại. Một multicharacter nghĩa đen có loại int và giá trị thực hiện.


11
Bạn đã không đề cập rằng đây là thực hiện được xác định.
Thomas Bonini

2
Tôi cho rằng điều thú vị nhất về định nghĩa đó sizeof(int)là việc triển khai cũng được xác định. Vì vậy, không chỉ thực hiện thứ tự lưu trữ được xác định, mà độ dài tối đa của chúng là tốt.
bobobobo

74

Không, đó không phải là một địa chỉ. Đó là cái gọi là nhân vật đa bào.

Thông thường, đó là giá trị ASCII của bốn ký tự được kết hợp.

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

Vậy 0x74657374 là 1952805748.

Nhưng nó cũng có thể là 0x74736574 trên một số trình biên dịch khác. Các tiêu chuẩn C và C ++ đều nói rằng giá trị của các ký tự đa bào được triển khai được xác định . Vì vậy, nói chung việc sử dụng nó được khuyến khích mạnh mẽ .


Là độ dài của một ký tự nhiều byte như vậy bị ràng buộc đến 4 byte? Tức là nó đại diện cho một int viết ra như các nhân vật?
Giorgio

2
@Giorgio: Tiêu chuẩn chỉ nói rằng việc triển khai được xác định, không có thêm chi tiết. Trong thực tế, vì intlà 4 byte trên hầu hết các máy, tôi không nghĩ việc sử dụng nhiều hơn 4 byte là hợp lý. Đúng, nó được dự định là một cách thuận tiện để viết một số hằng, nhưng thật không may, các trình biên dịch khác nhau đã diễn giải nó theo cách khác nhau, vì vậy ngày nay hầu hết các kiểu mã hóa không khuyến khích sử dụng nó.
chys

2
@chys: Và thực tế là nó được xác định theo cách triển khai có nghĩa là nó thậm chí không bắt buộc phải nhất quán. Ví dụ, một trình biên dịch tuân thủ có thể cung cấp cho tất cả các ký tự đa chủng loại giá trị 0 (mặc dù điều đó sẽ không thân thiện).
Keith Thompson

2
Người ta phải hỏi tại sao tính năng loony này tồn tại trong tiêu chuẩn. Có vẻ như một trường hợp sử dụng hiếm gặp như vậy, dù sao thì việc triển khai được xác định và có thể được thực hiện khá rõ ràng với sự dịch chuyển và thông thường của bit thông thường nếu cần.
Boann

1
@Boann Vâng , tình cảm của tôi chính xác. Nhưng bạn có thể sử dụng nó một cách an toàn trong các công tắc và không có gì, vì so sánh trực tiếp ==nên kiểm tra
bobobobo

18

Một ký tự thông thường có chứa nhiều hơn một c-char là một nghĩa đen đa chủng loại. Một multicharacter nghĩa đen có loại int và giá trị thực hiện.

Hành vi xác định thực hiện được yêu cầu phải được ghi lại bằng cách thực hiện. ví dụ trong gcc bạn có thể tìm thấy nó ở đây

Trình biên dịch định giá một ký tự nhiều ký tự một ký tự tại một thời điểm, thay đổi giá trị trước đó bằng số bit trên mỗi ký tự đích và sau đó hoặc nhập vào mẫu bit của ký tự mới được cắt theo chiều rộng của mục tiêu tính cách. Mẫu bit cuối cùng được đưa ra kiểu int và do đó được ký, bất kể các ký tự đơn có được ký hay không.

Kiểm tra lời giải thích trong trang này để biết thêm chi tiết


10

Họ thực sự chỉ là ints. Ví dụ, chúng được sử dụng rộng rãi trong enum của Core Audio API, trong CoreAudioTypes.htệp tiêu đề,

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

Có rất nhiều câu chuyện phiếm về việc không phải là "độc lập với nền tảng", nhưng khi bạn sử dụng một api được tạo ra cho một nền tảng cụ thể, người quan tâm đến tính di động. Kiểm tra sự bình đẳng trên cùng một nền tảng sẽ không bao giờ thất bại. Các enumgiá trị này dễ đọc hơn và chúng thực sự chứa danh tính của chúng trong giá trị của chúng , khá đẹp.

Những gì tôi đã cố gắng làm dưới đây là bọc một ký tự đa nhân theo nghĩa đen để nó có thể được in (trên Mac này hoạt động). Điều kỳ lạ là, nếu bạn không sử dụng hết 4 ký tự, kết quả sẽ trở nên sai dưới đây ..

#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
"Kiểm tra sự bình đẳng trên cùng một nền tảng sẽ không bao giờ thất bại." Nó có thể. Nâng cấp lên Visual Studio xyz và cắn lưỡi. Thư viện này đã đưa ra một quyết định khủng khiếp .
Các cuộc đua nhẹ nhàng trong quỹ đạo

@LightnessRacesinOrbit "Nâng cấp lên Visual Studio xyz và cắn lưỡi của bạn." API Core Audio là API âm thanh hệ thống của OS X nên điều này không liên quan.
Jean-Michaël Celerier 16/07/2016

5
@ Jean-MichaëlCelerier: Tốt; nâng cấp phiên bản OSX Clang của bạn và cắn lưỡi ...
Các cuộc đua nhẹ nhàng trong quỹ đạo

1

Loại tính năng này thực sự tốt khi bạn đang xây dựng trình phân tích cú pháp. Xem xét điều này:

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

Mã này có thể sẽ chỉ hoạt động trên endianess cụ thể và có thể phá vỡ các trình biên dịch khác nhau

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.