How to write an unsigned short int literal?

C++Types

C++ Problem Overview


42 as unsigned int is well defined as "42U".

unsigned int foo = 42U; // yeah!

How can I write "23" so that it is clear it is an unsigned short int?

unsigned short bar = 23; // booh! not clear!

EDIT so that the meaning of the question is more clear:

template <class T>
void doSomething(T) {
    std::cout << "unknown type" << std::endl;
}

template<>
void doSomething(unsigned int) {
    std::cout << "unsigned int" << std::endl;
}

template<>
void doSomething(unsigned short) {
    std::cout << "unsigned short" << std::endl;
}

int main(int argc, char* argv[])
{
    doSomething(42U);
    doSomething((unsigned short)23); // no other option than a cast?

    return EXIT_SUCCESS;
}

C++ Solutions


Solution 1 - C++

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.

Solution 2 - C++

unsigned short bar = (unsigned short) 23;

or in new speak....

unsigned short bar = static_cast<unsigned short>(23);

Solution 3 - C++

at least in Visual Studio (at least 2013 and newer) you can write

23ui16

for get an constant of type unsigned short.

see definitions of INT8_MIN, INT8_MAX, INT16_MIN, INT16_MAX, etc. macros in stdint.h

I don't know at the moment whether this is part of the standard C/C++

Solution 4 - C++

There are no modifiers for unsigned short. Integers, which has int type by default, usually implicitly converted to target type with no problems. But if you really want to explicitly indicate type, you could write the following:

unsigned short bar = static_cast<unsigned short>(23);

As I can see the only reason is to use such indication for proper deducing template type:

func( static_cast<unsigned short>(23) );

But for such case more clear would be call like the following:

func<unsigned short>( 23 );

Solution 5 - C++

There are multiple answers here, none of which are terribly satisfying. So here is a compilation answer with some added info to help explain things a little more thoroughly.

First, avoid shorts as suggested, but if you find yourself needing them such as when working with indexed mesh data and simply switching to shorts for your index size cuts your index data size in half...then read on...

1 While it is technically true that there is no way to express an unsigned short literal in c or C++ you can easily side step this limitation by simply marking your literal as unsigned with a 'u'.

unsigned short myushort = 16u;

This works because it tells the compiler that 16 is unsigned int, then the compiler goes looking for a way to convert it to unsigned short, finds one, most compilers will then check for overflow, and do the conversion with no complaints. The "narrowing conversion" error/warning when the "u" is left out is the compiler complaining that the code is throwing away the sign. Such that if the literal is negative such as -1 then the result is undefined. Usually this means you will get a very large unsigned value that will then be truncated to fit the short.

2 There are multiple suggestions on how to side step this limitation, most seasoned programmers will sum these up with a "don't do that".

unsigned short myshort = (unsigned short)16;
unsigned short myothershort = static_cast<unsigned short>(16);

While both of these work they are undesirable for 2 major reasons. First they are wordy, programmers get lazy and typing all that just for a literal is easy to skip which leads to basic errors that could have been avoided with a better solution. Second they are not free, static_cast in particular generates a little assembly code to do the conversion, and while an optimizer may(or may not) figure out that it can do the conversion its better to just write good quality code from the start.

unsigned short myshort = 16ui16;

This solution is undesirable because it limits who can read your code and understand it, it also means you are starting down the slippery slope of compiler specific code which can lead to your code suddenly not working because of the whims of some compiler writer, or some company that randomly decides to "make a right hand turn", or goes away and leaves in you in the lurch.

unsigned short bar = L'\x17';

This is so unreadable that nobody has upvoted it. And unreadable should be avoided for many good reasons.

unsigned short bar = 0xf;

This to is unreadable. While being able to read understand and convert hex is something serious programmers really need to learn it is very unreadable quick what number is this: 0xbad; Now convert it to binary...now octal.

3 Lastly if you find all the above solutions undesirable I offer up yet another solution that is available via a user defined operator.

constexpr unsigned short operator ""_ushort(unsigned long long x) 
{ 
    return (unsigned short)x; 
}

and to use it

unsigned short x = 16_ushort;

Admittedly this too isn't perfect. First it takes an unsigned long long and whacks it all the way down to an unsigned short suppressing potential compiler warnings along the way, and it uses the c style cast. But it is constexpr which gurantees it is free in an optimized program, yet can be stepped into during debug. It is also short and sweet so programmers are more likely to use it and it is expressive so it is easy to read and understand. Unfortunately it requires a recent compiler as what can legally be done with user defined operators has changed over the various version of C++.

So pick your trade off but be careful as you may regret them later. Happy Programming.

Solution 6 - C++

Unfortunately, the only method defined for this is

> One or two characters in single quotes > ('), preceded by the letter L

According to http://cpp.comsci.us/etymology/literals.html

Which means you would have to represent your number as an ASCII escape sequence:

unsigned short bar = L'\x17';

Solution 7 - C++

Unfortunately, they can't. But if people just look two words behind the number, they should clearly see it is a short... It's not THAT ambiguous. But it would be nice.

Solution 8 - C++

If you express the quantity as a 4-digit hex number, the unsigned shortness might be clearer.

unsigned short bar = 0x0017;

Solution 9 - C++

You probably shouldn't use short, unless you have a whole lot of them. It's intended to use less storage than an int, but that int will have the "natural size" for the architecture. Logically it follows that a short probably doesn't. Similar to bitfields, this means that shorts can be considered a space/time tradeoff. That's usually only worth it if it buys you a whole lot of space. You're unlikely to have very many literals in your application, though, so there was no need foreseen to have short literals. The usecases simply didn't overlap.

Solution 10 - C++

In C++11 and beyond, if you really want an unsigned short literal conversion then it can be done with a user defined literal:

using uint16 = unsigned short;
using uint64 = unsigned long long;

constexpr uint16 operator""_u16(uint64 to_short) {
    // use your favorite value validation
    assert(to_short < USHRT_MAX); // USHRT_MAX from limits.h
    return static_cast<uint16>(to_short);
}


int main(void) {
  uint16 val = 26_u16;
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionmoalaView Question on Stackoverflow
Solution 1 - C++Steve JessopView Answer on Stackoverflow
Solution 2 - C++AnthonyLambertView Answer on Stackoverflow
Solution 3 - C++TeaAge81View Answer on Stackoverflow
Solution 4 - C++Kirill V. LyadvinskyView Answer on Stackoverflow
Solution 5 - C++pmw1234View Answer on Stackoverflow
Solution 6 - C++Tyler McHenryView Answer on Stackoverflow
Solution 7 - C++micmooView Answer on Stackoverflow
Solution 8 - C++bobbymcrView Answer on Stackoverflow
Solution 9 - C++MSaltersView Answer on Stackoverflow
Solution 10 - C++pmw1234View Answer on Stackoverflow