4.13 — Literals

In programming, a constant is a fixed value that may not be changed. C++ has two kinds of constants: literal constants, and symbolic constants. We’ll cover literal constants in this lesson, and symbolic constants in the next lesson.

Literal constants (usually just called literals) are values inserted directly into the code. For example:

They are constants because their values can not be changed dynamically (you have to change them, and then recompile for the change to take effect).

Just like objects have a type, all literals have a type. The type of a literal is assumed from the value and format of the literal itself.

By default:

Literal value Examples Default type
integral value 5, 0, -3 int
boolean value true, false bool
floating point value 3.4, -2.2 double (not float)!
char value ‘a’ char
C-style string “Hello, world!” const char[14]

Literal suffixes

If the default type of a literal is not as desired, you can change the type of a literal by adding a suffix:

Data Type Suffix Meaning
int u or U unsigned int
int l or L long
int ul, uL, Ul, UL, lu, lU, Lu, or LU unsigned long
int ll or LL long long
int ull, uLL, Ull, ULL, llu, llU, LLu, or LLU unsigned long long
double f or F float
double l or L long double

You generally won’t need to use suffixes for integer types, but here are examples:

By default, floating point literal constants have a type of double. To make them float literals instead, the f (or F) suffix should be used:

New programmers are often confused about why the following doesn’t work as expected:

Because 4.1 has no suffix, it’s treated as a double literal, not a float literal. When C++ defines the type of a literal, it does not care what you’re doing with the literal (e.g. in this case, using it to initialize a float variable). Therefore, the 4.1 must be converted from a double to a float before it can be assigned to variable f, and this could result in a loss of precision.

Literals are fine to use in C++ code so long as their meanings are clear. This is most often the case when used to initialize or assign a value to a variable, do math, or print some text to the screen.

String literals

In lesson 4.11 -- Chars, we defined a string as a collection of sequential characters. C++ supports string literals:

String literals are handled very strangely in C++ for historical reasons. For now, it’s fine to use string literals to print text with std::cout, but don’t try and assign them to variables or pass them to functions -- it either won’t work, or won’t work like you’d expect. We’ll talk more about C-style strings (and how to work around all of those odd issues) in future lessons.

Scientific notation for floating point literals

There are two different ways to declare floating-point literals:

In the second form, the number after the exponent can be negative:

Octal and hexadecimal literals

In everyday life, we count using decimal numbers, where each numerical digit can be 0, 1, 2, 3, 4, 5, 6, 7, 8, or 9. Decimal is also called “base 10”, because there are 10 possible digits (0 through 9). In this system, we count like this: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, … By default, numbers in C++ programs are assumed to be decimal.

In binary, there are only 2 digits: 0 and 1, so it is called “base 2”. In binary, we count like this: 0, 1, 10, 11, 100, 101, 110, 111, …

There are two other “bases” that are sometimes used in computing: octal, and hexadecimal.

Octal is base 8 -- that is, the only digits available are: 0, 1, 2, 3, 4, 5, 6, and 7. In Octal, we count like this: 0, 1, 2, 3, 4, 5, 6, 7, 10, 11, 12, … (note: no 8 and 9, so we skip from 7 to 10).

Decimal 0 1 2 3 4 5 6 7 8 9 10 11
Octal 0 1 2 3 4 5 6 7 10 11 12 13

To use an octal literal, prefix your literal with a 0:

This program prints:


Why 10 instead of 12? Because numbers are printed in decimal, and 12 octal = 10 decimal.

Octal is hardly ever used, and we recommend you avoid it.

Hexadecimal is base 16. In hexadecimal, we count like this: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F, 10, 11, 12, …

Decimal 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
Hexadecimal 0 1 2 3 4 5 6 7 8 9 A B C D E F 10 11

To use a hexadecimal literal, prefix your literal with 0x.

This program prints:


Because there are 16 different values for a hexadecimal digit, we can say that a single hexadecimal digit encompasses 4 bits. Consequently, a pair of hexadecimal digits can be used to exactly represent a full byte.

Consider a 32-bit integer with value 0011 1010 0111 1111 1001 1000 0010 0110. Because of the length and repetition of digits, that’s not easy to read. In hexadecimal, this same value would be: 3A7F 9826. This makes hexadecimal values useful as a concise way to represent a value in memory. For this reason, hexadecimal values are often used to represent memory addresses or raw values in memory.

Prior to C++14, there is no way to assign a binary literal. However, hexadecimal pairs provide us with a useful workaround:

C++14 binary literals and digit separators

In C++14, we can assign binary literals by using the 0b prefix:

Because long literals can be hard to read, C++14 also adds the ability to use a quotation mark (‘) as a digit separator.

If your compiler isn’t C++14 compatible, your compiler will complain if you try to use either of these.

Printing decimal, octal, hexadecimal, and binary numbers

By default, C++ prints values in decimal. However, you can tell it to print in other formats. Printing in decimal, octal, or hex is easy via use of std::dec, std::oct, and std::hex:

This prints:


Printing in binary is a little harder, as std::cout doesn’t come with this capability built-in. Fortunately, the C++ standard library includes a type called std::bitset that will do this for us (in the <bitset> header). To use std::bitset, we can define a std::bitset variable and tell std::bitset how many bits we want to store. The number of bits must be a compile time constant. std::bitset can be initialized with an unsigned integral value (in any format, including decimal, octal, hex, or binary).

This prints:

11000101 11000101

We can also create a temporary (anonymous) std::bitset to print a single value. In the above code, this line:

creates a temporary std::bitset object with 4 bits, initializes it with 0b1010, prints the value in binary, and then discards the temporary std::bitset.

Magic numbers, and why they are bad

Consider the following snippet:

A number such as the 30 in the snippet above is called a magic number. A magic number is a literal (usually a number) in the middle of the code that does not have any context. What does 30 mean? Although you can probably guess that in this case it’s the maximum number of students per class, it’s not absolutely clear. In more complex programs, it can be very difficult to infer what a hard-coded number represents, unless there’s a comment to explain it.

Using magic numbers is generally considered bad practice because, in addition to not providing context as to what they are being used for, they pose problems if the value needs to change. Let’s assume that the school buys new desks that allow them to raise the class size from 30 to 35, and our program needs to reflect that. Consider the following program:

To update our program to use the new classroom size, we’d have to update the constant 30 to 35. But what about the call to setMax()? Does that 30 have the same meaning as the other 30? If so, it should be updated. If not, it should be left alone, or we might break our program somewhere else. If you do a global search-and-replace, you might inadvertently update the argument of setMax() when it wasn’t supposed to change. So you have to look through all the code for every instance of the literal 30, and then determine whether it needs to change or not. That can be seriously time consuming (and error prone).

Although we say magic “numbers”, this affects all kinds of values. Consider this example

There’s only one number (100) in this example, but it’s also used in the strings. If we decide to update the maximum to let’s say 200, we have to update three different occasions of 100.

Fortunately, better options (symbolic constants) exist. We’ll talk about those in the next lesson.

Best practice

Don’t use magic numbers in your code.

4.14 -- Const, constexpr, and symbolic constants
4.12 -- An introduction to std::string

180 comments to 4.13 — Literals

  • Zablas

    Hi there! I have one question about magic numbers. The basic solution would be to put them into variables right? But won't we start taking up memory once we put every single magic number into a variable? That could cause optimisation problems.

    • Alex

      Generally if you put them into const variables, the compiler will be able to optimize the variables away. That gives you all of the maintainability benefits for no performance cost.

  • Ronald

    your saying long and int are literals yet they can be changed in the program

    • Alex

      You can have int literals and long literals. They can be changed, but you'll have to recompile afterward. You can't change them at runtime.

  • Lakshmanan Kanthi

    Is 0x10 a hexadecimal literal or a binary literal? How do we differentiate between the two in the versions prior to c++14?



  • One Manual

    Literal constants (usually just called “literals”) are values inserted directly into the code. They are constants because you can’t change their values. For example:

    int x = 5;

    But isnt this a variable that i can change anytime? im sry, im confused in this one, literal constants are variables too? why they are called constant then?

    Please help me :(

  • Felipe

    Looks like someone has had a bad time with magic numbers :)

  • Philip

    In the code fragment on hexidecimal below

    on line 15

    you have the incorrect binary value for B. it should be 1011 not 1010

  • Matt

    Typo towards the end of section "Literal constants":
    "By default, floating point literal constant have a type of double."

    "Constant" should be plural.

  • Nguyen

    Hi Alex,

    There are many vital pieces of information about "Binary" in section 2.1 & 2.3 (... all data on a computer is just a sequence of bits.....When you assign a value to a data type, the compiler and CPU take care of the details of encoding your value into the appropriate sequence of bits for that data type. When you ask for your value back, your number is “reconstituted” from the sequence of bits in memory....)

    In this section, Octal and Hexadecimal are introduced...but I don't know what they are for?

    Thanks, Have a nice day.

    • Alex

      As I mention in the lesson, octal is hardly ever used, so you can basically forget about it.

      Hexadecimal values are used a lot though, mainly because two hexadecimal values cover 8 bits, which is a byte. Therefore, when we talk about the contents of a memory address (which are a byte), instead of representing those contents as 8 binary digits, it's much easier to represent them as 2 hexadecimal digits.

  • bert

    I believe you meant to use "ways" in the following line:

    While boolean and integer literals are pretty straightforward, there are two different way to declare floating-point literals:

    thanks - appreciate all your hard work!

  • Nyap

    does gcc support C++14?

    • Alex

      Yes, some newer versions do. But you have to pass it a flag to enable that functionality (-std=c++14 or -std=c++1y, depending on gcc version)

  • Maxwell Pollack

    I'm CLICKING ON EVERY AD!  You're welcome.

  • Oeleo

    Hello, I tried to do a converter decimal/hexadecimal or decimal/octal with his code :

    But it seems that using 0x01 and 0number doesn't work if you write it in the consol. Is their any way to create a converter like that ?

  • Oeleo

    I don't really understand the definition of litteral, because in math I found this definition :
    "Literal numbers are the letters which are used to represent a number."
    But here it seems to have a totally different signification, but which ?

  • Bill

    Your syntax highlighter certainly makes a mess of the infix apostrophes in binary literals...I guess it's not C++14 compliant :-)

  • crazyD

    alex, thx for all these best tuts. i want to ask u, are u now going to write tuts for some other platforms also or not?? will be best for me if u will write javaEE.

  • TheSuitIsNotBlack

    I'm confused about the float type default of double. Why isn't the default of float set to float? It seems weird to have to use a suffix to specify that the type should be float for a type that's already been defined as float. Where does the double come in?

    • Alex

      Are you asking why for the following:

      4.0 isn't assumed to be a float since it's assigned to a float variable? I presume because:
      * C doesn't have type inference (C++11 does, but this was inherited from C).
      * Type inference works from right to left, not left to right.
      * This gives the programmer has explicit control over what 4.0 means (type double) regardless of what's on the left-hand side of the literal.

  • Roee Sefi

    Why 10 instead of 12? Because numbers are stored in decimal, and 12 octal = 10 decimal.

    I think it should be:
    Because numbers are being printed in... (or something)
    They actually stored in binary.

  • Aryan

    HI there Alex,

    I am a bit confused as to why one needs to type in the suffixes of the data types? They are not necessary right?

    • Alex

      The suffixes of the data types tell C++ how to interpret a literal.

      For example, if you type in 5.2, C++ knows this is a floating point literal, but it doesn't know whether you meant a float or a double. So it assumes double.

      If you wanted/needed 5.2 to be a float, you're better off specifying the literal as 5.2f, so C++ knows you meant a float, not a double.

      Otherwise, if you do this:

      C++ will convert 5.2 from a double to a float before assigning to variable f, and you may lose some precision.

      Suffixes are only needed if the default type for a literal isn't sufficient for your needs. Generally, when using literals, it's a good idea to ensure your literal has the same type as the variable it's being assigned to, to minimize the chance of something unexpectedly going wrong somewhere.

  • Yujian

    A question: why FF in hexadecimal is 255 in decimal?

    • Alejandro

      That's simple hexa coding, you definitely should re-read about it.

      "F" in hexa stands for a "15" in decimal (1,2,3,4,5,6,7,8,9,A,B,C,D,E,F), so when you have 0xFF to convert it to decimal:
      0xFF = F * 16^1 + F * 16^0 = 15 * 16 + 15 = 240 + 15 = 255.


  • gigi

    Hi Alex
    Can you add ";" to your examples?

  • Steve

    A good thing to have in mind counting in oct and hex:
    oct is base 8, so starting the count is 0, 1, 2, 3, 4, 5, 6, 7
    all 8 digits were used, so now we add 1 to the left: 10, 11, 12, 13, 14, 15, 16, 17
    20, 21, 22, 23, 24, 25, 26, 27 etc.
    same for hex, base 16:
    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F
    add 1 left:
    10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 1A, 1B, 1C, 1D, 1E, 1F
    this principle is for decimal as well, just an easy way to count...

  • Kanchana

    I think you made a typo here

    above code should be


  • The last example seems to have wrong comments:

    should be:

    Thanks for the tutorial !

  • PaulS

    Above you have: Octal is base 8 — that is, the only digits available are: 0, 1, 2, 3, 4, 5, 6, 7, 8.

    That would be base 9, though, right?

  • linuxx

    Hi! I'm not totally new to C++, but new to this course. (Yes, I'm calling it a "course" 'cause it's better than all other C++ teaching I've come across in the past - THANK YOU SO MUCH!)

    Anyhow... I've been digging through the tutorials very seriously. All of the stuff is really well explained and if a piece of information happens to be missing, it is usually covered by the comments. However, here (in 2.8), I'm a bit lost... Can you explain to me, why we'd want to add an "L" to

    long nValue2 = 5L;

    or an f to

    float fValue = 5.0f;


    They have already been declared as being "long" and "float"... So what's the point here...???


    • Alex

      There aren't a whole lot of reasons you'd need to specify the L prefix.

      But lets say you had two functions:
      void doSomething(int);
      void doSomething(long);

      if you called doSomething(5), you'd get the int version instead of the long version. Using doSomething(5L) would get you version that takes the long parameter.

      There are probably other obscure examples.

      The f prefix is used more commonly, because floating point numbers have weird truncation/rounding issues.

      Consider the following code:

      This prints "not equal"! Why? When 0.67 gets assigned to f, it gets truncated to 0.670000017. When you compare that truncated value to the double value 0.67, it doesn't match!

      This one works as expected:

  • Hi Alex,
    I'm new to c++. My question may be dump to you but what's the difference between "int = 5" or "int == 5".

    • dospy

      there is no such thing like "int = 5" or “int == 5?
      "int" is a keyword used to define variables type

  • pravin

    this is very nice tutorial..
    i m not new to c++ also not proficient but getting good concepts from this tutorial

  • Alex:

    Ref.: it is a good idea to try to avoid using literal constants that aren't 0 or 1.

    So I should use only literal constants that are 0 or 1? As for above.

  • Literal constants are literal numbers inserted into the code. They are constants because you can't change their values.

    int x = 5; // 5 is a literal constant

    I don't understand this, you can change 5 to 6, how is it unchangable?

    • If you use the number 6 instead of 5, you are using a different literal, not changing the value of a literal. In other words, literals are constants because the symbol 5 always has the value 5. You can't change the symbol 5 to the value 6, or any other number.

    • Elpidius

      When declaring an integer variable that isn't const, the value of the variable x can be reassigned to, later on.

      int x = 5; // declares x as an integer variable and assigns 5 to x
      x = 2; // 2 is now assigned to x, instead of 5
      x = 4; // 4 is now assigned to x, instead of 2

      In the above example, x is declared and the number 5 is assigned to x. We can then assign another number to x later on, which will then change the value of x.

      We can check that the values have changed by printing them to the console:

      using namespace std;
      int x = 5;
      cout << x << endl; // the value of x displayed here is 5
      x = 2;
      cout << x << endl; // the value changes to 2
      x = 4;
      cout << x << endl; // now it is 4

      This outputs:

      However when we declare a variable as const, and assign a value to it, we cannot assign another value later on:

      const int x = 5; // declares x as an constant integer variable and assigns 5 to x
      x = 2; // compiler error, as we cannot assign another value to x

      Although the compiler comes up with an error "you cannot assign to a variable that is const", this is misleading, as you can assign (initialize) a literal constant to a variable only once. Consequently its value remains constant throughout the entire program.

      P.S. I'm also a newbie learning C++, but I'm just getting this logic from what Alex has written in the past, along with some practise on Visual C++ 2010 Express!

      P.P.S. I'm loving these tutorials Alex ;)

Leave a Comment

Put all code inside code tags: [code]your code here[/code]