5

I can not understand what the purpose is of type modifiers for literal constants, like for numerical constants:

75 
75u     
75l  
75ul
75lu 

In what cases could this possibly be useful? I mean if you already have declared a type modifier for the variable type, I do not see a need for this. If anybody could help me understand this, it would be amazing! Thanks!

Bonus question: Is "literal" the same as "constant" like could you just say "literal" instead of "literal constant"?

phuclv
  • 37,963
  • 15
  • 156
  • 475
  • These are literal values , not variables – M.M Mar 24 '17 at 07:53
  • I know,I have not said that they were variables, right? –  Mar 24 '17 at 07:54
  • you said "type modifier for the variable type" – M.M Mar 24 '17 at 07:54
  • A little bit of reading: http://en.cppreference.com/w/cpp/language/integer_literal – Rerito Mar 24 '17 at 07:54
  • Yea.. I said that because I do not understand if you already have declared the type modifier for the variable, like "unsigned int name", I do not see why you would need to set the numerical constant to have a type modifier of maybe unsigned too, so it would be "unsigned int name = 88u" –  Mar 24 '17 at 07:56
  • 1
    what if you were not assigning it to a variable? – M.M Mar 24 '17 at 08:13

3 Answers3

9

Sometimes a literal must have a specific type. For example

void foo(const int&){
    // pay myself
}

void foo(const unsigned&){
    // reformat my disk
}

Then foo(75) and foo(75u) would have very different outcomes.

Infact, it is so useful, that from C++11 it's possible to define your own literal types. See http://en.cppreference.com/w/cpp/language/user_literal

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • Yeah, also sometimes you're storing a literal value in a non-const variable. Type modifiers NEED to exist for that reason. Saying "but we have const already" is missing the point because it's ignoring the situations where the variable we're putting things in isn't const. – Jason Lang Mar 24 '17 at 08:04
4

For integer literals, apart from what's in Bathsheba's answer, it's also used for various cases like suppressing warnings

unsigned int n = somevalue;
...
if (n > 5) dosomething();

Changing to if (n > 5U) and there'll be no more warnings.

Or when you do something like this

long long x = 1 << 50;

and realized that x is not what you expected, you need to change it to

long long x = 1LL << 50;

Another usage is for the auto keyword in C++11

auto a = 1;
auto b = 1U;
auto c = 1L;
auto d = 1UL;

The above will result in different types for the variable

For floating-point literals, using suffix will result in more correct result

long double a = 0.01234567890123456789;
long double a = 0.01234567890123456789L;

Those may result in very very different values. That's because a literal without suffix is a double literal value and will be rounded correctly to double, hence when long double has more precision than double it'll result in precision lost. The same will occur with floats due to double-rounding (first to double then to float, instead of directly round the literal to float)

if (0.67 == 0.67f)
   std::cout << "Equal";
else 
   std::cout << "Not Equal";

The above will print out "Not Equal"

What is the difference between casting to float and adding f as a suffix when initializing a float?

Community
  • 1
  • 1
phuclv
  • 37,963
  • 15
  • 156
  • 475
  • @Lundin it'll generate a ["comparison between signed and unsigned" warning](http://stackoverflow.com/a/859979/995714). I don't get your latter point. `1 << 50` is an int expression which results in undefined behavior – phuclv Mar 24 '17 at 10:49
  • You wrote "long double a = 0.01234567890123456789L;", so would you need the long suffix if the variable type already is long and you therefore can type any value that is valid for this type? –  Mar 24 '17 at 17:57
  • @sostack yes you always need the suffix, because otherwise it'll be rounded at double precision then upcast into long double as I said, and you'll lost digits at the end. see [The precision of the long double output is not correct. What might be wrong?](http://stackoverflow.com/q/684112/995714), [Why do you need to append an L or F after a value assigned to a C++ constant?](http://stackoverflow.com/q/1380653/995714), [Actual long double precision does not agree with std::numeric_limits](http://stackoverflow.com/q/2565512/995714)... – phuclv Mar 25 '17 at 02:21
0

One of the most common cases where I see this is in 75ul << 18. The input to the shift needs to have enough bits to allow that shift. 75 might be 16 bits, making a shift over 18 bits Undefined Behavior (bad). 75ul is at least 32 bits.

MSalters
  • 173,980
  • 10
  • 155
  • 350