Comment écrire un court littéral en C ++?

120

Question très basique: comment écrire un shortlittéral en C ++?

Je sais ce qui suit:

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

Mais comment écrire un shortlittéral? J'ai essayé 2Smais cela donne un avertissement au compilateur.

Kip
la source
10
Je suppose que le littéral court n'est pas pris en charge uniquement en raison du fait que tout ce qui est inférieur à int sera "promu" en int pendant l'évaluation. int a la taille la plus naturelle. C'est ce qu'on appelle la promotion d'entiers en C ++.
user534498

Réponses:

82
((short)2)

Ouais, ce n'est pas strictement un court littéral, plutôt un casted-int, mais le comportement est le même et je pense qu'il n'y a pas de moyen direct de le faire.

C'est ce que j'ai fait parce que je n'ai rien trouvé à ce sujet. Je suppose que le compilateur serait assez intelligent pour compiler cela comme s'il s'agissait d'un littéral court (c'est-à-dire qu'il n'allouerait pas réellement un int et le transtyperait à chaque fois).

Ce qui suit illustre à quel point vous devriez vous inquiéter à ce sujet:

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

Compiler -> démonter ->

movl    $2, _a
movl    $2, _b
movl    $2, _c
movl    $2, _d
Jonathan Leffler
la source
C'est ce que j'ai fait parce que je n'ai rien trouvé à ce sujet. Je suppose que le compilateur serait assez intelligent pour compiler ceci comme s'il s'agissait d'un littéral court (c'est-à-dire qu'il n'allouerait pas réellement un int et le transtyperait à chaque fois).
Kip
Le "casting" ne fait vraiment rien. Il n'y a pas d'instruction d'assembleur "cast" lorsque nous parlons de C ou C ++ (.NET MSIL est une histoire différente cependant). Là-bas sur le métal, ce ne sont que des chiffres binaires
Isak Savo
9
Quels sont les types de a, b, c et d ci-dessus?
Ates Goral
2
@Ates Goral: Tous les ints. Changer en short ou char changerait vraisemblablement l'instruction en movw ou movb à tous les niveaux.
2
Ce n'est pas littéralement court. Lorsque vous utilisez ce cast et compilez avec GCC et l'option -Wconversion, vous obtenez toujours un diagnostic du compilateur pour l'instruction short foo = 1; foo += (short)2;. Mais cela ne peut pas être contourné en raison de la promotion entière.
harper
51

C ++ 11 vous donne assez proche de ce que vous voulez. (Recherchez "littéraux définis par l'utilisateur" pour en savoir plus.)

#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
la source
6
shortphysiquement ne peut pas être std::uintquelque chose, car il s'agit d'un type signé. Et il n'est pas nécessaire qu'il s'agisse de 16 bits ou du même type qu'un std::int16_t... qui lui-même n'est même pas obligé d' exister dans une implémentation donnée si la plate-forme ne peut pas fournir le type de largeur exacte. L'idée de base de cette réponse est bonne, mais elle est dévaluée par la tangente inexplicable en types non liés que l'OP n'a pas posé de questions.
underscore_d
Remarque les littéraux définis par l'utilisateur ne sont pas pris en charge dans Visual Studio jusqu'à VS2015: msdn.microsoft.com/en-us/library/hh567368(v=vs.140).aspx
parsley72
Je ne sais pas si je devrais l'aimer ou le détester, mais c'est le dernier élément de mon système de type entier Strong en C ++ sur lequel je travaille, c'est incroyable.
Sahsahae
en écho à @underscore_d, je voterais pour mais après une modification, shortcomme l'a demandé OP.
v.oddou
28

Même les auteurs de la norme C99 ont été surpris par cela. Voici un extrait de l' stdint.himplémentation du domaine public 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
la source
18

Si vous utilisez Microsoft Visual C ++, des suffixes littéraux sont disponibles pour chaque type d'entier:

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

Notez que ce sont une extension non standard et ne sont pas portables . En fait, je n'ai même pas pu trouver d'informations sur ces suffixes sur MSDN.

Alexandre Revo
la source
1
Lorsque vous tracez l'un des suffixes, vous verrez que eg ""ui8est défini comme '\000', qui est essentiellement '\0'.
Nikita
10

Vous pouvez également utiliser la syntaxe de pseudo-constructeur.

short(2)

Je le trouve plus lisible que le casting.

Jimvonmoon
la source
4
cela s'appelle une "expression de distribution fonctionnelle". Je l'aime beaucoup aussi, surtout lors de la programmation avec l'API Windows.
klaus triendl
6

Autant que je sache, ce n'est pas le cas, il n'y a pas de suffixe. La plupart des compilateurs avertiront si un littéral entier est trop grand pour tenir dans la variable dans laquelle vous essayez de le stocker.

se détendre
la source