Что делают одинарные кавычки в 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
Вы не упомянули, что это определяется реализацией.
Томас Бонини

2
Я полагаю, что самое забавное в этом определении то, что sizeof(int)он также определяется реализацией. Таким образом, определяется не только реализация порядка хранения, но и их максимальная длина.
Бобобобо

74

Нет, это не адрес. Это так называемый многобайтовый символ.

Как правило, это значения ASCII четырех символов вместе взятых.

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

Так что 0x74657374 это 1952805748.

Но это также может быть 0x74736574 на другом компиляторе. Оба стандарта C и C ++ говорят, что значение многобайтовых символов определяется реализацией . Таким образом , как правило , его использование настоятельно рекомендуется.


Ограничена ли длина такого многобайтового символа 4 байтами? Т.е. он представляет собой int, записанный в виде символов?
Джорджио

2
@ Джорджио: Стандарт только говорит, что он определен реализацией, без каких-либо подробностей. На практике, поскольку intна большинстве машин 4 байта, я не думаю, что имеет смысл использовать более 4 байтов. Да, он задумывался как удобный способ написания некоторых констант, но, к сожалению, разные компиляторы интерпретировали его по-разному, поэтому в настоящее время большинство стилей кодирования не поощряют его использование.
Чи

2
@chys: И тот факт, что он определяется реализацией, означает, что даже не требуется быть последовательным. Например, соответствующий компилятор может дать всем литералам с несколькими символами значение 0 (хотя это будет недружественным).
Кит Томпсон

2
Нужно спросить, почему эта стандартная функция существует в стандарте. Кажется, что это такой редкий случай использования, реализация в любом случае определена, и может быть сделано довольно четко с обычным сдвигом битов и или, если необходимо.
Boann

1
@ Boann Да , мои чувства точно. Но вы можете смело использовать его в коммутаторах и еще много чего, так как прямое сравнение ==должно быть проверено
bobobobo

18

Обычный символьный литерал, содержащий более одного символа c-char, является литералом с несколькими символами. Литерал с несколькими символами имеет тип int и значение, определяемое реализацией.

Поведение, определяемое реализацией, должно быть задокументировано реализацией. например, в GCC вы можете найти его здесь

Компилятор определяет многосимвольную символьную константу по символу за раз, сдвигая предыдущее значение влево на количество битов на целевой символ, а затем перемещая его в битовом массиве нового символа, урезанного до ширины целевого объекта. персонаж. Конечный битовый шаблон имеет тип int и поэтому подписан независимо от того, подписаны ли отдельные символы или нет.

Проверьте объяснение на этой странице для более подробной информации


10

Они действительно просто intс. Они широко используются в перечислении Core Audio API, например, в 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 и прикусите язык. Эта библиотека приняла ужасное решение.
Гонки легкости на орбите

@LightnessRacesinOrbit « Перейдите на Visual Studio xyz и прикусите язык». Core Audio API - это системный аудио API OS X, так что это не имеет значения.
Жан-Мишель Селерье

5
@ Жан-Михаэль Келерье: Отлично; обнови свою версию OSX Clang и прикуси язык ...
Гонки на Легкость на Орбите

1

Такая функция действительно хороша, когда вы создаете парсеры. Учти это:

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

Этот код, скорее всего, будет работать только с определенным порядком байтов и может разбиваться на разные компиляторы

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.