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

Мне любопытен этот код:

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

дает мне результат 1952805748.

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


person lucidreality    schedule 18.09.2011    source источник
comment
Обратите внимание, что фактическое значение определяется реализацией stackoverflow.com/questions/3960954/c- многосимвольный-буквальный   -  person FireAphis    schedule 18.09.2011


Ответы (5)


Это многосимвольный литерал. 1952805748 - это 0x74657374, который разлагается как

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

Изменить:

Стандарт C ++, §2.14.3 / 1 - Символьные литералы

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

person K-ballo    schedule 18.09.2011
comment
Вы не упомянули, что это определяется реализацией. - person Thomas Bonini; 18.09.2011
comment
Я полагаю, что самое забавное в этом определении - это то, что sizeof(int) также определяется реализацией. Таким образом, определяется не только реализация порядка хранения, но и максимальная их длина. - person bobobobo; 28.12.2013

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

Обычно это значения ASCII четырех вместе взятых символов.

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

So 0x74657374 is 1952805748.

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

person chys    schedule 18.09.2011
comment
Ограничена ли длина такого многобайтового символа 4 байтами? Т.е. представляет ли он int, записанный как символы? - person Giorgio; 18.09.2011
comment
@Giorgio: В стандарте только сказано, что реализация определена, без каких-либо подробностей. На практике, поскольку int на большинстве машин составляет 4 байта, я не думаю, что имеет смысл использовать более 4 байтов. Да, это было задумано как удобный способ написания некоторых констант, но, к сожалению, разные компиляторы интерпретируют его по-разному, поэтому в настоящее время большинство стилей кодирования не поощряют его использование. - person chys; 18.09.2011
comment
@chys: И тот факт, что он определяется реализацией, означает, что он даже не обязан быть последовательным. Соответствующий компилятор мог бы дать всем многосимвольным литералам, например, значение 0 (хотя это было бы недружелюбно). - person Keith Thompson; 18.09.2011
comment
Возникает вопрос, почему эта дурацкая функция существует в стандарте. Кажется, что это такой редкий вариант использования, реализация которого все равно определена и может быть реализована довольно четко с помощью обычного сдвига битов и или, если необходимо. - person Boann; 23.02.2013
comment
@Boann Да, в точности мои чувства. Но вы можете безопасно использовать его в переключателях и многом другом, так как прямое сравнение для == должно проверить - person bobobobo; 21.12.2013

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

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

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

Ознакомьтесь с объяснением в эта страница для получения дополнительной информации.

person Mouna Cheikhna    schedule 19.09.2011

Они действительно просто ints. Они широко используются в перечислениях Core Audio API, например, в заголовочном файле CoreAudioTypes.h,

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

Много говорят о том, что это не «платформенно-независимый», но когда вы используете api, созданный для конкретной платформы, кого волнует переносимость. Проверка на равенство на одной платформе никогда не завершится ошибкой. Эти enum'd значения легче читать, и они фактически содержат свою идентичность в своем значении, что довольно приятно.

То, что я пытался сделать ниже, - это обернуть многобайтовый символьный литерал, чтобы его можно было распечатать (на 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;
}
person bobobobo    schedule 28.12.2013
comment
Проверка на равенство на одной платформе никогда не завершится ошибкой. Может. Обновитесь до Visual Studio xyz и прикусите язык. Эта библиотека приняла ужасное решение. - person Lightness Races in Orbit; 31.07.2015
comment
@LightnessRacesinOrbit Обновитесь до Visual Studio xyz и прикусите язык. Core Audio API - это API системного звука OS X, поэтому это не актуально. - person Jean-Michaël Celerier; 16.07.2016
comment
@ Жан-Мишель Селерье: Хорошо; обновите версию OSX Clang и прикусите язык ... - person Lightness Races in Orbit; 16.07.2016

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

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

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

person Ayende Rahien    schedule 06.07.2017