Come scrivo un breve letterale in C ++?


120

Domanda molto semplice: come si scrive un shortletterale in C ++?

So quanto segue:

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

Ma come scriverei un shortletterale? Ho provato 2Sma questo dà un avvertimento al compilatore.


10
Immagino che il letterale corto non sia supportato solo per il fatto che qualsiasi cosa inferiore a int verrà "promossa" a int durante la valutazione. int ha la dimensione più naturale. Questa è chiamata promozione di numeri interi in C ++.
user534498

Risposte:


82
((short)2)

Sì, non è strettamente letterale breve, più di un cast-int, ma il comportamento è lo stesso e penso che non ci sia un modo diretto per farlo.

È quello che ho fatto perché non sono riuscito a trovare nulla al riguardo. Immagino che il compilatore sarebbe abbastanza intelligente da compilarlo come se fosse un letterale breve (cioè non allocherebbe effettivamente un int e poi lo cast ogni volta).

Quanto segue illustra quanto dovresti preoccuparti di questo:

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

Compila -> disassembla ->

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

È quello che ho fatto perché non sono riuscito a trovare nulla al riguardo. Immagino che il compilatore sarebbe abbastanza intelligente da compilarlo come se fosse un letterale breve (cioè non allocherebbe effettivamente un int e poi lo cast ogni volta).
Kip

Il "cast" non sta davvero facendo nulla. Non ci sono istruzioni assembler "cast" quando parliamo di C o C ++ (.NET MSIL è una storia diversa però). Là sul metallo, sono solo cifre binarie
Isak Savo

9
Quali sono i tipi di a, b, ced sopra?
Ates Goral

2
@Ates Goral: Tutti gli int. Cambiare in short o char cambierebbe presumibilmente l'istruzione in movw o movb su tutta la linea.

2
Non è letterale breve. Quando usi quel cast e compili con GCC e l'opzione -Wconversion ottieni ancora una diagnostica del compilatore per l'istruzione short foo = 1; foo += (short)2;. Ma questo non può essere aggirato a causa della promozione di numeri interi.
Harper

51

C ++ 11 ti dà molto vicino a quello che vuoi. (Cerca "letterali definiti dall'utente" per saperne di più.)

#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
shortfisicamente non può essere un std::uintniente, in quanto è un tipo con segno. E non è necessario che sia a 16 bit o dello stesso tipo di un std::int16_t... che di per sé non è nemmeno necessario che esista in una data implementazione se la piattaforma non può fornire il tipo di larghezza esatta. L'idea centrale di questa risposta è buona, ma è svalutata dall'inspiegabile tangente in tipi non correlati che l'OP non ha chiesto.
underscore_d

Nota letterali definiti dall'utente non sono supportati in Visual Studio fino VS2015: msdn.microsoft.com/en-us/library/hh567368(v=vs.140).aspx
parsley72

Non so se dovrei amarlo o odiarlo, ma questo è l'ultimo pezzo del mio sistema di tipi interi Strong in C ++ su cui sto lavorando, è sorprendente.
Sahsahae

facendo eco a @underscore_d, vorrei votare ma dopo una modifica a shortcome richiesto da OP.
v.oddou

28

Anche gli autori dello standard C99 sono stati colti di sorpresa da questo. Questo è uno snippet stdint.hdell'implementazione di dominio pubblico di Danny Smith :

/* 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

Se utilizzi Microsoft Visual C ++, sono disponibili suffissi letterali per ogni tipo di numero intero:

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

Nota che si tratta di un'estensione non standard e non sono portatili . In effetti, non sono riuscito nemmeno a trovare alcuna informazione su questi suffissi su MSDN.


1
Quando rintracci uno dei suffissi, vedrai che eg ""ui8è definito come '\000', che è essenzialmente '\0'.
Nikita

10

È inoltre possibile utilizzare la sintassi dello pseudo costruttore.

short(2)

Lo trovo più leggibile del casting.


4
si chiama "espressione cast funzionale". Mi piace molto anche, soprattutto quando si programma con l'API di Windows.
klaus triendl

6

Per quanto ne so, non lo fai, non esiste un suffisso del genere. La maggior parte dei compilatori avviserà se un intero letterale è troppo grande per adattarsi a qualsiasi variabile in cui si sta tentando di memorizzarlo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.