Как мне написать короткий литерал на C ++?


120

Очень простой вопрос: как мне написать shortлитерал на C ++?

Знаю следующее:

  • 2 является int
  • 2U является unsigned int
  • 2L это long
  • 2LL это long long
  • 2.0f это float
  • 2.0 это double
  • '\2'это а char.

Но как мне написать shortбуквальное? Я пробовал, 2Sно это дает предупреждение компилятору.


10
Я предполагаю, что короткий литерал не поддерживается исключительно из-за того, что все, что меньше int, будет "повышено" до int во время оценки. int имеет наиболее естественный размер. В C ++ это называется целочисленным продвижением.
user534498

Ответы:


82
((short)2)

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

Я этим и занимался, потому что ничего не мог найти об этом. Я бы предположил, что компилятор был бы достаточно умен, чтобы скомпилировать это, как если бы это был короткий литерал (т.е. он фактически не выделял бы int, а затем приводил бы его каждый раз).

Следующее показывает, насколько вам следует об этом беспокоиться:

a = 2L;
b = 2.0;
c = (short)2;
d = '\2';

Скомпилировать -> разобрать ->

movl    $2, _a
movl    $2, _b
movl    $2, _c
movl    $2, _d

Я этим и занимался, потому что ничего не мог найти об этом. Я бы предположил, что компилятор будет достаточно умен, чтобы скомпилировать это, как если бы это был короткий литерал (т.е. он фактически не выделял бы int, а затем приводил бы его каждый раз).
Кип,

«Актеры» на самом деле ничего не делают. Когда мы говорим о C или C ++, не существует инструкции ассемблера «cast» (хотя .NET MSIL - это совсем другая история). Там, на металле, это всего лишь двоичные цифры
Исак Саво

9
Какие типы a, b, c и d указаны выше?
Атес Горал,

2
@Ates Goral: Все целые. Переход на short или char, по-видимому, повлечет за собой изменение инструкции на movw или movb по всем направлениям.

2
Это не короткий буквальный смысл. Когда вы используете это приведение и компилируете с GCC и опцией -Wconversion, вы все равно получаете диагностику компилятора для оператора short foo = 1; foo += (short)2;. Но этого не избежать из-за целочисленной промо-акции.
harper

51

C ++ 11 дает вам довольно близко к тому, что вы хотите. (Чтобы узнать больше, выполните поиск по запросу "определяемые пользователем литералы".)

#include <cstdint>

inline std::uint16_t operator "" _u(unsigned long long value)
{
    return static_cast<std::uint16_t>(value);
}

void func(std::uint32_t value); // 1
void func(std::uint16_t value); // 2

func(0x1234U); // calls 1
func(0x1234_u); // calls 2

// also
inline std::int16_t operator "" _s(unsigned long long value)
{
    return static_cast<std::int16_t>(value);
}

6
shortфизически не может быть std::uintничем, так как это знаковый тип. И это не обязательно должны быть либо 16 бит или же типа как std::int16_t... которая сама по себе даже не требуется , чтобы существовать в данной реализации , если платформа не может поставить точный тип ширины. Основная идея этого ответа хороша, но она обесценивается необъяснимым касанием к несвязанным типам, о которых OP не спрашивал.
underscore_d

Обратите внимание, что определяемые пользователем литералы не поддерживаются в Visual Studio до VS2015: msdn.microsoft.com/en-us/library/hh567368(v=vs.140).aspx
parsley72

Не знаю, любить я это или ненавидеть, но это последняя часть моей действительно сильной системы целочисленных типов в C ++, над которой я работаю, это потрясающе.
Sahsahae

повторяя @underscore_d, я бы проголосовал за, но после редактирования, на которое shortответил OP.
v.oddou

28

Это застало даже разработчиков стандарта C99. Это отрывок из реализации Дэнни Смита в общественном достоянии stdint.h:

/* 7.18.4.1  Macros for minimum-width integer constants

    Accoding to Douglas Gwyn <gwyn@arl.mil>:
    "This spec was changed in ISO/IEC 9899:1999 TC1; in ISO/IEC
    9899:1999 as initially published, the expansion was required
    to be an integer constant of precisely matching type, which
    is impossible to accomplish for the shorter types on most
    platforms, because C99 provides no standard way to designate
    an integer constant with width less than that of type int.
    TC1 changed this to require just an integer constant
    *expression* with *promoted* type."
*/

18

Если вы используете Microsoft Visual C ++, для каждого целочисленного типа доступны буквальные суффиксы:

auto var1 = 10i8;  // char
auto var2 = 10ui8; // unsigned char

auto var3 = 10i16;  // short
auto var4 = 10ui16; // unsigned short

auto var5 = 10i32;  // int
auto var6 = 10ui32; // unsigned int

auto var7 = 10i64;  // long long
auto var8 = 10ui64; // unsigned long long

Обратите внимание, что это нестандартное расширение и его нельзя переносить . Фактически, я даже не смог найти никакой информации об этих суффиксах на MSDN.


1
Когда вы проследите один из суффиксов, вы увидите, что eg ""ui8определяется как '\000', что по сути является '\0'.
Никита

10

Вы также можете использовать синтаксис псевдоконструктора.

short(2)

Я считаю это более читаемым, чем кастинг.


4
это называется «функциональным выражением приведения». Мне это тоже очень нравится, особенно при программировании с помощью Windows API.
klaus triendl

6

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

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