Wie schreibe ich ein kurzes Literal in C ++?

120

Sehr grundlegende Frage: Wie schreibe ich ein shortLiteral in C ++?

Ich kenne folgendes:

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

Aber wie würde ich ein shortLiteral schreiben ? Ich habe es versucht, 2Saber das gibt eine Compiler-Warnung.

Pennen
quelle
10
Ich denke, kurzes Literal wird nicht nur aufgrund der Tatsache unterstützt, dass weniger als int während der Evaluierung zu int "befördert" wird. int hat die natürlichste Größe. Dies wird in C ++ als Ganzzahl-Heraufstufung bezeichnet.
user534498

Antworten:

82
((short)2)

Ja, es ist nicht nur ein kurzes Wort, sondern eher ein Casted-Int, aber das Verhalten ist das gleiche und ich denke, es gibt keinen direkten Weg, dies zu tun.

Das habe ich getan, weil ich nichts darüber finden konnte. Ich würde vermuten, dass der Compiler klug genug wäre, dies so zu kompilieren, als wäre es ein kurzes Literal (dh er würde nicht wirklich ein int zuweisen und es dann jedes Mal umwandeln).

Das Folgende zeigt, wie sehr Sie sich darüber Sorgen machen sollten:

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

Kompilieren -> zerlegen ->

movl    $2, _a
movl    $2, _b
movl    $2, _c
movl    $2, _d
Jonathan Leffler
quelle
Das habe ich getan, weil ich nichts darüber finden konnte. Ich würde vermuten, dass der Compiler klug genug wäre, dies so zu kompilieren, als wäre es ein kurzes Literal (dh er würde nicht wirklich ein int zuweisen und es dann jedes Mal umwandeln).
Kip
Die "Besetzung" macht eigentlich nichts. Es gibt keine Assembler-Anweisung "cast", wenn es sich um C oder C ++ handelt (.NET MSIL ist jedoch eine andere Geschichte). Dort auf dem Metall ist alles nur binäre Ziffern
Isak Savo
9
Welche Arten von a, b, c und d gibt es oben?
Ates Goral
2
@Ates Goral: Alle Ints. Ein Wechsel zu short oder char würde vermutlich die Anweisung in movw oder movb auf der ganzen Linie ändern.
2
Das ist kein kurzes Wort. Wenn Sie diese Umwandlung verwenden und mit GCC und der Option -Wconversion kompilieren, erhalten Sie weiterhin eine Compilerdiagnose für die Anweisung short foo = 1; foo += (short)2;. Dies kann jedoch aufgrund der Ganzzahl-Promotion nicht umgangen werden.
Harper
51

Mit C ++ 11 kommen Sie dem, was Sie wollen, ziemlich nahe. (Suchen Sie nach "benutzerdefinierten Literalen", um mehr zu erfahren.)

#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
quelle
6
shortphysisch kann std::uintnichts sein, da es ein signierter Typ ist. Und es ist nicht als entweder 16 Bit oder die gleiche Art wie ein erforderlich std::int16_t... , die sich nicht einmal erforderlich ist, existieren in einer gegebenen Implementierung , wenn die Plattform nicht die genaue Breitentyp liefern kann. Die Kernidee dieser Antwort ist gut, aber sie wird durch die unerklärliche Tangente an nicht verwandte Typen abgewertet, nach denen das OP nicht gefragt hat.
underscore_d
Hinweis Benutzerdefinierte Literale werden in Visual Studio erst in VS2015 unterstützt: msdn.microsoft.com/en-us/library/hh567368(v=vs.140).aspx
Petersilie72
Ich weiß nicht, ob ich es lieben oder hassen soll, aber dies ist das letzte Stück meines eigentlich starken Integer-Systems in C ++, an dem ich arbeite. Es ist erstaunlich.
Sahsahae
Echo @underscore_d, würde ich aber nach einer Bearbeitung auf shortwie von OP aked upvote.
v.oddou
28

Sogar die Autoren des C99-Standards waren davon betroffen. Dies ist ein Ausschnitt aus der gemeinfreien stdint.hImplementierung von 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
quelle
18

Wenn Sie Microsoft Visual C ++ verwenden, sind für jeden Ganzzahltyp Literalsuffixe verfügbar:

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

Beachten Sie, dass dies eine nicht standardmäßige Erweiterung ist und nicht portabel ist . Tatsächlich konnte ich auf MSDN nicht einmal Informationen zu diesen Suffixen finden.

Alexander Revo
quelle
1
Wenn Sie eines der Suffixe verfolgen, werden Sie sehen, dass zB ""ui8definiert ist als '\000', was im Wesentlichen ist '\0'.
Nikita
10

Sie können auch die Pseudokonstruktorsyntax verwenden.

short(2)

Ich finde es lesbarer als Casting.

Jimvonmoon
quelle
4
Es wird als "funktionaler Besetzungsausdruck" bezeichnet. Ich mag es auch sehr, besonders wenn ich mit der Windows-API programmiere.
Klaus Triendl
6

Soweit ich weiß, gibt es kein solches Suffix. Die meisten Compiler warnen jedoch, wenn ein ganzzahliges Literal zu groß ist, um in die Variable zu passen, in der Sie es speichern möchten.

entspannen
quelle