Jak napisać krótki literał w C ++?

120

Bardzo podstawowe pytanie: jak napisać shortliterał w C ++?

Wiem co następuje:

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

Ale jak napisałbym shortdosłowne? Próbowałem, 2Sale to daje ostrzeżenie kompilatora.

Wyrko
źródło
10
Wydaje mi się, że krótki dosłowny nie jest obsługiwany wyłącznie ze względu na fakt, że wszystko mniejsze niż int będzie „promowane” do int podczas oceny. int ma najbardziej naturalny rozmiar. Nazywa się to promocją liczb całkowitych w C ++.
user534498

Odpowiedzi:

82
((short)2)

Tak, to nie jest ściśle krótki, dosłowny, raczej casted-int, ale zachowanie jest takie samo i myślę, że nie ma bezpośredniego sposobu, aby to zrobić.

To właśnie robiłem, ponieważ nie mogłem nic znaleźć na ten temat. Wydaje mi się, że kompilator byłby wystarczająco inteligentny, aby skompilować to tak, jakby był to krótki literał (tj. W rzeczywistości nie przydzielałby int, a następnie rzutowałby go za każdym razem).

Poniższe ilustruje, jak bardzo powinieneś się tym martwić:

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

Kompiluj -> deasembluj ->

movl    $2, _a
movl    $2, _b
movl    $2, _c
movl    $2, _d
Jonathan Leffler
źródło
To właśnie robiłem, ponieważ nie mogłem nic znaleźć na ten temat. Wydaje mi się, że kompilator byłby wystarczająco inteligentny, aby skompilować to tak, jakby był to krótki literał (tj. W rzeczywistości nie przydzielałby int, a następnie rzutowałby go za każdym razem).
Kip
„Obsada” tak naprawdę nic nie robi. Nie ma instrukcji asemblera "rzutowanych", gdy mówimy o C lub C ++ (.NET MSIL to jednak inna historia). Na metalu są to tylko cyfry binarne
Isak Savo,
9
Jakie są typy a, b, c i d powyżej?
Ates Goral
2
@Ates Goral: All ints. Zmiana na krótki lub zwęglony prawdopodobnie zmieniłaby instrukcję poruszania się lub poruszania po planszy.
2
To nie jest krótkie dosłowne. Gdy używasz tego rzutowania i kompilujesz z GCC i opcją -Wconversion, nadal otrzymujesz diagnostykę kompilatora dla instrukcji short foo = 1; foo += (short)2;. Ale nie można tego obejść ze względu na promocję liczb całkowitych.
harper
51

C ++ 11 daje ci prawie to, czego chcesz. (Wyszukaj „literały zdefiniowane przez użytkownika”, aby dowiedzieć się więcej).

#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
źródło
6
shortfizycznie nie może być std::uintniczym, ponieważ jest to typ ze znakiem. I nie jest wymagane, aby mieć 16 bitów lub ten sam typ, co std::int16_t..., który sam w sobie nie musi nawet istnieć w danej implementacji, jeśli platforma nie może dostarczyć typu o dokładnej szerokości. Podstawowa idea tej odpowiedzi jest dobra, ale jest zdewaluowana przez niewytłumaczalną styczną do niepowiązanych typów, o które OP nie pytał.
underscore_d
Uwaga: literały zdefiniowane przez użytkownika nie są obsługiwane w programie Visual Studio do VS2015: msdn.microsoft.com/en-us/library/hh567368(v=vs.140).aspx
parsley72
Nie wiem, czy powinienem go kochać, czy nienawidzić, ale jest to ostatni element mojego systemu typów całkowitych Strong w C ++, nad którym pracuję, jest niesamowity.
Sahsahae
echo @underscore_d, zagłosowałbym za, ale po edycji shortzgodnie z OP.
v.oddou
28

Nawet pisarze standardu C99 zostali przez to złapani. To jest fragment z stdint.himplementacji domeny publicznej Danny'ego Smitha :

/* 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
źródło
18

Jeśli używasz programu Microsoft Visual C ++, dla każdego typu liczby całkowitej dostępne są dosłowne sufiksy:

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

Pamiętaj, że są to niestandardowe rozszerzenia i nie są przenośne . W rzeczywistości nie mogłem nawet znaleźć żadnych informacji o tych sufiksach w witrynie MSDN.

Alexander Revo
źródło
1
Kiedy prześledzisz jeden z przyrostków, zobaczysz, że np. ""ui8Jest zdefiniowany jako '\000', czyli zasadniczo '\0'.
Nikita
10

Możesz także użyć składni pseudo-konstruktora.

short(2)

Uważam to za bardziej czytelne niż casting.

jimvonmoon
źródło
4
nazywa się to „wyrażeniem rzutowania funkcjonalnego”. Bardzo mi się to podoba, zwłaszcza gdy programuję za pomocą Windows API.
klaus triendl
6

O ile wiem, nie masz, nie ma takiego przyrostka. Większość kompilatorów ostrzeże jednak, jeśli literał całkowity jest zbyt duży, aby zmieścić się w dowolnej zmiennej, w której próbujesz go przechowywać.

rozwijać
źródło