Что делают одинарные кавычки в C ++ при использовании нескольких символов?

279

Мне интересно этот код:

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

дает мне вывод 1952805748.

Мой вопрос: вывод адрес в памяти или что-то?

lucidreality
источник
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 и значение, определяемое реализацией.

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

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

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

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

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

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

chys
источник
Ограничена ли длина такого многобайтового символа 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;
}
bobobobo
источник
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);

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

Ayende Rahien
источник