Como escrevo um literal curto em C ++?

120

Pergunta muito básica: como eu escrevo um shortliteral em C ++?

Eu sei o seguinte:

  • 2 é um int
  • 2U é um unsigned int
  • 2L é um long
  • 2LL é um long long
  • 2.0f é um float
  • 2.0 é um double
  • '\2'é um char.

Mas como eu escreveria um shortliteral? Eu tentei, 2Smas isso dá um aviso do compilador.

Kip
fonte
10
Eu acho que o literal curto não é suportado apenas devido ao fato de que algo menor que int será "promovido" a int durante a avaliação. int tem o tamanho mais natural. Isso é chamado de promoção inteira em C ++.
User534498

Respostas:

82
((short)2)

Sim, não é estritamente um literal curto, é mais um cast-int, mas o comportamento é o mesmo e acho que não há uma maneira direta de fazê-lo.

É o que tenho feito porque não consegui encontrar nada sobre isso. Eu acho que o compilador seria inteligente o suficiente para compilar isso como se fosse um literal curto (ou seja, na verdade, ele não alocaria um int e depois o lançaria toda vez).

A seguir, ilustra o quanto você deve se preocupar com isso:

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

Compilar -> desmontar ->

movl    $2, _a
movl    $2, _b
movl    $2, _c
movl    $2, _d
Jonathan Leffler
fonte
É o que tenho feito porque não consegui encontrar nada sobre isso. Eu acho que o compilador seria inteligente o suficiente para compilar isso como se fosse um literal curto (ou seja, na verdade, não alocaria um int e depois o lançaria toda vez).
Kip
O "elenco" não está realmente fazendo nada. Não há instruções do assembler "cast" quando falamos de C ou C ++ (o .NET MSIL é uma história diferente). Há sobre o metal, é todos os dígitos apenas binários
Isak Savo
9
Quais são os tipos de a, b, ce acima?
Ates Goral 16/10/08
2
@Ates Goral: Todos os ints. Mudar para short ou char provavelmente mudaria a instrução para movw ou movb no quadro.
2
Isso não é literal curto. Quando você usa essa conversão e compila com o GCC e a opção -Wconversion, você ainda recebe um diagnóstico do compilador para a instrução short foo = 1; foo += (short)2;. Mas isso não pode ser contornado devido à promoção inteira.
harper
51

O C ++ 11 oferece muito perto do que você deseja. (Pesquise "literais definidos pelo usuário" para saber mais.)

#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);
}
Ken Smith
fonte
6
shortfisicamente não pode ser std::uintnada, pois é um tipo assinado. E não é necessário que seja 16 bits ou o mesmo tipo de um std::int16_t... que nem sequer é necessário que exista em uma determinada implementação se a plataforma não puder fornecer o tipo de largura exata. A idéia central dessa resposta é boa, mas é desvalorizada pela tangente inexplicável em tipos não relacionados que o OP não perguntou.
Underscore_d
Literais definidos pelo utilizador de notas não são suportados no Visual Studio até VS2015: msdn.microsoft.com/en-us/library/hh567368(v=vs.140).aspx
parsley72
Não sei se devo amar ou odiá-lo, mas esta é a última parte do meu sistema de número inteiro Strong em C ++ em que estou trabalhando, é incrível.
Sahsahae 04/12/19
ecoando @underscore_d, gostaria de votar, mas depois de uma edição shortconforme solicitado pelo OP.
v.oddou
28

Até os escritores do padrão C99 foram surpreendidos por isso. Este é um trecho da stdint.himplementação de domínio público de Danny Smith :

/* 7.18.4.1  Macros for minimum-width integer constants

    Accoding to Douglas Gwyn <[email protected]>:
    "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."
*/
Michael Burr
fonte
18

Se você usa o Microsoft Visual C ++, existem sufixos literais disponíveis para cada tipo inteiro:

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

Observe que essas extensões não são padrão e não são portáteis . Na verdade, eu não conseguia nem localizar nenhuma informação sobre esses sufixos no MSDN.

Alexander Revo
fonte
1
Ao rastrear um dos sufixos, você verá que eg ""ui8é definido como '\000', o que é essencialmente '\0'.
Nikita
10

Você também pode usar a sintaxe do pseudo-construtor.

short(2)

Acho mais legível do que o elenco.

jimvonmoon
fonte
4
é chamado de "expressão de conversão funcional". Também gosto muito, especialmente ao programar com a API do Windows.
Klaus Triendl
6

Até onde eu sei, você não sabe, não existe esse sufixo. A maioria dos compiladores avisa se um literal inteiro é muito grande para caber em qualquer variável em que você esteja tentando armazená-lo.

descontrair
fonte