How to Write a Short Literal in C++

How do I write a short literal in C++?

((short)2)

Yeah, it's not strictly a short literal, more of a casted-int, but the behaviour is the same and I think there isn't a direct way of doing it.

That's what I've been doing because I couldn't find anything about it. I would guess that the compiler would be smart enough to compile this as if it's a short literal (i.e. it wouldn't actually allocate an int and then cast it every time).

The following illustrates how much you should worry about this:

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

Compile -> disassemble ->

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

short int literals in C

It doesn't make sense to have a short int literal in C since all integer expressions are evaluated as if the subexpressions were at least int in size.

How to write an unsigned short int literal?

You can't. Numeric literals cannot have short or unsigned short type.

Of course in order to assign to bar, the value of the literal is implicitly converted to unsigned short. In your first sample code, you could make that conversion explicit with a cast, but I think it's pretty obvious already what conversion will take place. Casting is potentially worse, since with some compilers it will quell any warnings that would be issued if the literal value is outside the range of an unsigned short. Then again, if you want to use such a value for a good reason, then quelling the warnings is good.

In the example in your edit, where it happens to be a template function rather than an overloaded function, you do have an alternative to a cast: do_something<unsigned short>(23). With an overloaded function, you could still avoid a cast with:

void (*f)(unsigned short) = &do_something;
f(23);

... but I don't advise it. If nothing else, this only works if the unsigned short version actually exists, whereas a call with the cast performs the usual overload resolution to find the most compatible version available.

Literal for short or char (integers)

There are no suffixes for short types (types narrower than int) and you don't need them.

Outside of preprocessor conditionals, the suffixes can be fully expressed in terms of casts or more generically casts and the ternary operator ( 0xfffffffffU isn't equal to (unsigned)0xfffffffff, but it is equal to (1?0xfffffffff:0u) on platforms with 32-bit unsigneds).

In preprocessor conditionals, casts won't work, so you do need at least the U suffix there if you need unsigned semantics. The other suffixes, I guess, are just for convenience for when a macro needs to be used in both C and in preprocessor conditionals, although things like ((type)+42) can also be employed in such situations (relying on keywords expanding to 0 in preprocessor conditionals).

As Eric Pospitschil has pointed out, preprocessor arithmetic is done in intmax_t/uintmax_t so you don't need to widen the constants as you would in C proper to prevent some instances of undefined behavior.

How to specify a short int literal without casting?

Short answer, No. In C#, there's no letter S that could be used as var a = 123S that would indicate that a is of type short. There's L for long, F for float, D for double, M for decimal, but not S. It would be nice if there was, but there isn't.

var a = 1M;  // decimal
var a = 1L; // long
var a = 1F; // float
var a = 1D; // double
var a = 1; // int

var a = 1U; // uint
var a = 1UL; // ulong

but not

var a = 1S; // not possible, you must use (short)1;

C# short/long/int literal format?

var d  = 1.0d;  // double
var d0 = 1.0; // double
var d1 = 1e+3; // double
var d2 = 1e-3; // double
var f = 1.0f; // float
var m = 1.0m; // decimal
var i = 1; // int
var ui = 1U; // uint
var ul = 1UL; // ulong
var l = 1L; // long

I think that's all... there are no literal specifiers for short/ushort/byte/sbyte

printf a literal number (int) while expecting a shorter number

printf() doesn't actually expect the argument to be a short when you use %hi. When you call a variadic function, all the arguments undergo default argument promotion. In the case of integer arguments, this means integer promotions, which means that all integer types smaller than int are converted to int or unsigned int.

If the corresponding argument is a literal, all that's required is that it be a value that will fit into a short, you don't actually have to cast it to short.

The standard section 7.21.6.1.7 explains it this way:

the argument will
have been promoted according to the integer promotions, but its value shall
be converted to short int or unsigned short int before printing

Is there a workaround to define a user-defined literal for shorts in c++?

As explained here, the unary - is applied to the result of 42_s, so it seems that integral promotion cannot be avoided. Depending on applications, the following workaround might be of some use:

struct Short {    
short v;

short operator+() const {
return v;
}

short operator-() const {
return -v;
}
};

Short operator"" _s(unsigned long long x) {
return Short{static_cast<short>(x)};
}

auto PositiveShort = +42_s;
auto NegativeShort = -42_s;

static_assert(std::is_same_v<decltype(PositiveShort), short>);
static_assert(std::is_same_v<decltype(NegativeShort), short>);

Does C++ allow any integer literal to be implicitly converted to a short int?

The standard allows the implicit conversion between any two integer types, regardless of their values.

The compiler warnings are unrelated to the code being legal; the compiler just warns you when your code probably does not do what you wanted it to.

In your specific case, n1 would be 8 and n2 would have an implementation defined value. Both assignments are legal C++, but the latter is probably not what you intended.


Relevant standardese:

A prvalue of an integer type can be converted to a prvalue of another integer type. A prvalue of an unscoped
enumeration type can be converted to a prvalue of an integer type.

If the destination type is unsigned, the resulting value is the least unsigned integer congruent to the source
integer (modulo 2n where n is the number of bits used to represent the unsigned type). [ Note: In a two’s
complement representation, this conversion is conceptual and there is no change in the bit pattern (if there
is no truncation). — end note ]

If the destination type is signed, the value is unchanged if it can be represented in the destination type (and
bit-field width); otherwise, the value is implementation-defined.

4.7/1-3 in N4141



Related Topics



Leave a reply



Submit