¿Cómo escribo un literal corto en C ++?

120

Pregunta muy básica: ¿cómo escribo un shortliteral en C ++?

Yo se lo siguiente:

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

Pero, ¿cómo escribiría un shortliteral? Lo intenté, 2Spero eso da una advertencia del compilador.

Dormir
fuente
10
Supongo que el literal corto no se admite únicamente debido al hecho de que cualquier cosa menor que int será "promocionada" a int durante la evaluación. int tiene el tamaño más natural. Esto se denomina promoción de enteros en C ++.
user534498

Respuestas:

82
((short)2)

Sí, no es estrictamente un literal corto, más bien un int casted, pero el comportamiento es el mismo y creo que no hay una forma directa de hacerlo.

Eso es lo que he estado haciendo porque no pude encontrar nada al respecto. Supongo que el compilador sería lo suficientemente inteligente como para compilar esto como si fuera un literal corto (es decir, no asignaría un int y luego lo lanzaría cada vez).

A continuación se muestra cuánto debería preocuparse por esto:

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
fuente
Eso es lo que he estado haciendo porque no pude encontrar nada al respecto. Supongo que el compilador sería lo suficientemente inteligente como para compilar esto como si fuera un literal corto (es decir, no asignaría un int y luego lo lanzaría cada vez).
Kip
El "elenco" realmente no está haciendo nada. No hay una instrucción de ensamblador "cast" cuando hablamos de C o C ++ (.NET MSIL es una historia diferente). Ahí en el metal, todo son solo dígitos binarios
Isak Savo
9
¿Cuáles son los tipos de a, b, cyd anteriores?
Ates Goral
2
@Ates Goral: Todas las entradas. Cambiar a short o char probablemente cambiaría la instrucción a movw o movb en todos los ámbitos.
2
Eso no es un literal corto. Cuando usa esa conversión y compila con GCC y la opción -Wconversion, aún obtiene un diagnóstico del compilador para la declaración short foo = 1; foo += (short)2;. Pero esto no se puede eludir debido a la promoción de números enteros.
harper
51

C ++ 11 le ofrece bastante cerca de lo que desea. (Busque "literales definidos por el usuario" para obtener más información).

#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
fuente
6
shortfísicamente no puede ser std::uintnada, ya que es un tipo firmado. Y no se requiere que sea de 16 bits o del mismo tipo que un std::int16_t... que en sí mismo ni siquiera se requiere que exista en una implementación dada si la plataforma no puede suministrar el tipo de ancho exacto. La idea central de esta respuesta es buena, pero está devaluada por la tangente inexplicable en tipos no relacionados sobre los que el OP no preguntó.
underscore_d
Tenga en cuenta que los literales definidos por el usuario no son compatibles con Visual Studio hasta VS2015: msdn.microsoft.com/en-us/library/hh567368(v=vs.140).aspx
parsley72
No sé si debería amarlo u odiarlo, pero esta es la última pieza de mi sistema de tipos enteros Strong en C ++ en la que estoy trabajando, es increíble.
Sahsahae
Haciendo eco de @underscore_d, votaría a favor, pero después de una edición shortsegún lo solicitó OP.
v.oddou
28

Incluso los escritores del estándar C99 quedaron atrapados por esto. Este es un fragmento de la stdint.himplementación de dominio 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
fuente
18

Si usa Microsoft Visual C ++, hay sufijos literales disponibles para cada tipo de entero:

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

Tenga en cuenta que se trata de una extensión no estándar y no es portátil . De hecho, ni siquiera pude encontrar información sobre estos sufijos en MSDN.

Alexander Revo
fuente
1
Cuando traza uno de los sufijos, verá que, por ejemplo, ""ui8se define como '\000', que es esencialmente '\0'.
Nikita
10

También puede utilizar la sintaxis de pseudoconstructor.

short(2)

Lo encuentro más legible que el casting.

Jimvonmoon
fuente
4
se llama "expresión de conversión funcional". También me gusta mucho, especialmente cuando programo con la API de Windows.
Klaus Triendl
6

Hasta donde yo sé, no es así, no existe tal sufijo. Sin embargo, la mayoría de los compiladores advertirán si un literal entero es demasiado grande para caber en cualquier variable en la que esté tratando de almacenarlo.

relajarse
fuente