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 unsigned
s).
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 toshort int
orunsigned 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
C/C++ Unsigned Integer Overflow
Strict Aliasing Rule and 'Char *' Pointers
Is the Size of Std::Array Defined by Standard
Efficient Implementation of Log2(_M256D) in Avx2
Why Do I See Strange Values When I Print Uninitialized Variables
C++ "Cin" Only Reads the First Word
Throwing Exceptions from Constructors
Why Would One Use Nested Classes in C++
What New Capabilities Do User-Defined Literals Add to C++
"X Does Not Name a Type" Error in C++
How Do Conversion Operators Work in C++
What Are the Best (Portable) Cross-Platform Arbitrary-Precision Math Libraries
Pinpointing "Conditional Jump or Move Depends on Uninitialized Value(S)" Valgrind Message
Why Is ++I Considered an L-Value, But I++ Is Not
C++11 Features in Visual Studio 2012
Can Standard Container Templates Be Instantiated With Incomplete Types