Search

4.11 — Chars

To this point, the fundamental data types we’ve looked at have been used to hold numbers (integers and floating point) or true/false values (booleans). But what if we want to store letters? The char data type was designed for such a purpose.

The char data type is an integral type, meaning the underlying value is stored as an integer, and it’s guaranteed to be 1-byte in size. However, similar to how a boolean value is interpreted as true or false, a char value is interpreted as an ASCII character.

ASCII stands for American Standard Code for Information Interchange, and it defines a particular way to represent English characters (plus a few other symbols) as numbers between 0 and 127 (called an ASCII code or code point). For example, ASCII code 97 is interpreted as the character ‘a’.

Character literals are always placed between single quotes.

Here’s a full table of ASCII characters:

Code Symbol Code Symbol Code Symbol Code Symbol
0 NUL (null) 32 (space) 64 @ 96 `
1 SOH (start of header) 33 ! 65 A 97 a
2 STX (start of text) 34 66 B 98 b
3 ETX (end of text) 35 # 67 C 99 c
4 EOT (end of transmission) 36 $ 68 D 100 d
5 ENQ (enquiry) 37 % 69 E 101 e
6 ACK (acknowledge) 38 & 70 F 102 f
7 BEL (bell) 39 71 G 103 g
8 BS (backspace) 40 ( 72 H 104 h
9 HT (horizontal tab) 41 ) 73 I 105 i
10 LF (line feed/new line) 42 * 74 J 106 j
11 VT (vertical tab) 43 + 75 K 107 k
12 FF (form feed / new page) 44 , 76 L 108 l
13 CR (carriage return) 45 - 77 M 109 m
14 SO (shift out) 46 . 78 N 110 n
15 SI (shift in) 47 / 79 O 111 o
16 DLE (data link escape) 48 0 80 P 112 p
17 DC1 (data control 1) 49 1 81 Q 113 q
18 DC2 (data control 2) 50 2 82 R 114 r
19 DC3 (data control 3) 51 3 83 S 115 s
20 DC4 (data control 4) 52 4 84 T 116 t
21 NAK (negative acknowledge) 53 5 85 U 117 u
22 SYN (synchronous idle) 54 6 86 V 118 v
23 ETB (end of transmission block) 55 7 87 W 119 w
24 CAN (cancel) 56 8 88 X 120 x
25 EM (end of medium) 57 9 89 Y 121 y
26 SUB (substitute) 58 : 90 Z 122 z
27 ESC (escape) 59 ; 91 [ 123 {
28 FS (file separator) 60 < 92 \ 124 |
29 GS (group separator) 61 = 93 ] 125 }
30 RS (record separator) 62 > 94 ^ 126 ~
31 US (unit separator) 63 ? 95 _ 127 DEL (delete)

Codes 0-31 are called the unprintable chars, and they’re mostly used to do formatting and control printers. Most of these are obsolete now.

Codes 32-127 are called the printable characters, and they represent the letters, number characters, and punctuation that most computers use to display basic English text.

Initializing chars

You can initialize char variables using character literals:

You can initialize chars with integers as well, but this should be avoided if possible

Warning

Be careful not to mix up character numbers with integer numbers. The following two initializations are not the same:

Character numbers are intended to be used when we want to represent numbers as text, rather than as numbers to apply mathematical operations to.

Printing chars

When using std::cout to print a char, std::cout outputs the char variable as an ASCII character:

This produces the result:

ab

We can also output char literals directly:

This produces the result:

c

A reminder

The fixed width integer int8_t is usually treated the same as a signed char in C++, so it will generally print as a char instead of an integer.

Printing chars as integers via type casting

If we want to output a char as a number instead of a character, we have to tell std::cout to print the char as if it were an integer. One (poor) way to do this is by assigning the char to an integer, and printing the integer:

However, this is clunky. A better way is to use a type cast. A type cast creates a value of one type from a value of another type. To convert between fundamental data types (for example, from a char to an int, or vice versa), we use a type cast called a static cast.

The syntax for the static cast looks a little funny:

static_cast<new_type>(expression)

static_cast takes the value from an expression as input, and converts it into whatever fundamental type new_type represents (e.g. int, bool, char, double).

Key insight

Whenever you see C++ syntax that makes use of angled brackets, the thing between the angled brackets will most likely be a type. This is typically how C++ deals with concepts that need a parameterizable type.

Here’s using a static cast to create an integer value from our char value:

This results in:

a
97
a

It’s important to note that the parameter to static_cast evaluates as an expression. When we pass in a variable, that variable is evaluated to produce its value, which is then converted to the new type. The variable is not affected by casting its value to a new type. In the above case, variable ch is still a char, and still holds the same value.

Also note that static casting doesn’t do any range checking, so if you cast an integer that is too big to fit into a char, you’ll overflow your char.

We’ll talk more about static casts and the different types of casts in a future lesson (S.4.4a -- Explicit type conversion (casting)).

Inputting chars

The following program asks the user to input a character, then prints out both the character and its ASCII code:

Here’s the output from one run:

Input a keyboard character: q
q has ASCII code 113

Note that std::cin will let you enter multiple characters. However, variable ch can only hold 1 character. Consequently, only the first input character is extracted into variable ch. The rest of the user input is left in the input buffer that std::cin uses, and can be extracted with subsequent calls to std::cin.

You can see this behavior in the following example:

Input a keyboard character: abcd
a has ASCII code 97
b has ASCII code 98

Char size, range, and default sign

Char is defined by C++ to always be 1 byte in size. By default, a char may be signed or unsigned (though it’s usually signed). If you’re using chars to hold ASCII characters, you don’t need to specify a sign (since both signed and unsigned chars can hold values between 0 and 127).

If you’re using a char to hold small integers (something you should not do unless you’re explicitly optimizing for space), you should always specify whether it is signed or unsigned. A signed char can hold a number between -128 and 127. An unsigned char can hold a number between 0 and 255.

Escape sequences

There are some characters in C++ that have special meaning. These characters are called escape sequences. An escape sequence starts with a ‘\’ (backslash) character, and then a following letter or number.

You’ve already seen the most common escape sequence: ‘\n’, which can be used to embed a newline in a string of text:

This outputs:

First line
Second line

Another commonly used escape sequence is ‘\t’, which embeds a horizontal tab:

Which outputs:

First part        Second part

Three other notable escape sequences are:
\’ prints a single quote
\” prints a double quote
\\ prints a backslash

Here’s a table of all of the escape sequences:

Name Symbol Meaning
Alert \a Makes an alert, such as a beep
Backspace \b Moves the cursor back one space
Formfeed \f Moves the cursor to next logical page
Newline \n Moves cursor to next line
Carriage return \r Moves cursor to beginning of line
Horizontal tab \t Prints a horizontal tab
Vertical tab \v Prints a vertical tab
Single quote \’ Prints a single quote
Double quote \” Prints a double quote
Backslash \\ Prints a backslash
Question mark \? Prints a question mark
Octal number \(number) Translates into char represented by octal

Hex number \x(number) Translates into char represented by hex number

Here are some examples:

Prints:

"This is quoted text"
This string contains a single backslash \
6F in hex is char 'o'

Newline (\n) vs. std::endl

We cover this topic in lesson 1.5 -- Introduction to iostream: cout, cin, and endl.

What’s the difference between putting symbols in single and double quotes?

As you learned above, chars are always put in single quotes (e.g. ‘a’, ‘+’, ‘5’). A char can only represent one symbol (e.g. the letter a, the plus symbol, the number 5). Something like this is illegal:

Text put between double quotes (e.g. “Hello, world!”) is called a string. A string is a collection of sequential characters (and thus, a string can hold multiple symbols).

For now, you’re welcome to use string literals in your code:

However, strings are not fundamental data types in C++, and are a little more complex, so we’ll reserve discussion of those until we cover compound types.

What about the other char types, wchar_t, char16_t, and char32_t?

wchar_t should be avoided in almost all cases (except when interfacing with the Windows API). Its size is implementation defined, and is not reliable. It has largely been deprecated.

Much like ASCII maps the integers 0-127 to American English characters, other character encoding standards exist to map integers (of varying sizes) to characters in other languages. The most well-known mapping outside of ASCII is the Unicode standard, which maps over 110,000 integers to characters in many different languages. Because Unicode contains so many code points, a single Unicode code point needs 32-bits to represent a character (called UTF-32). However, Unicode characters can also be encoded using multiple 16-bit or 8-bit characters (called UTF-16 and UTF-8 respectively).

char16_t and char32_t were added to C++11 to provide explicit support for 16-bit and 32-bit Unicode characters. char8_t has been added in C++20.

You won’t need to use char8_t, char16_t, or char32_t unless you’re planning on making your program Unicode compatible. Unicode and localization are generally outside the scope of these tutorials, so we won’t cover it further.

In the meantime, you should only use ASCII characters when working with characters (and strings). Using characters from other character sets may cause your characters to display incorrectly.


4.12 -- Literals
Index
4.10 -- Introduction to if statements

191 comments to 4.11 — Chars

  • learning

    hey, what is the meaning of the '\h'?

  • Samira Ferdi

    Hi Alex and Nascardriver!

    I've found that the addition of char type is like the addition of it's ASCII code.
    For example '5' + '5' means 53 + 53 and prints in the console 106. Is this a standard or just compiler-specific behavior?

    • It's standard. `char` is an integral type and can be used in arithmetic (With care to integral promotion). The only thing special about `char` is that in addition to it's integral representation, it has a character representation.

  • BP

    Hello!

    A quick question:
    How does the \a work?
    Because I can't seem to get an alert of any kind...

    Thanks,

    Edit: Or \f, tried it in std::cout and I got a symbol. I'm guessing that we will learn more about \f when we learn about logical pages?

  • alfonso

    Unexpected thing:

    error: multi-line comment [-Werror=comment]

    • Alex

      Yes, \ at the end of a line is a line-continuation character, meaning the next line is treated as an extension of the previous line.

  • alfonso

    Why to escape ' (single quote) there? More generally, why to escape a single quote? Ok, I can see one use case for escaping single quote

  • Louis Cloete

    Hi @Alex!

    The program example just above "Char size, range, and default sign" still uses std::endl for line breaks.

  • Somoshree Datta

    Hi Alex, your tutorials are really awesome! I have this one doubt:
    In the previous tutorials, you had said that std::cout flushes the output, i.e. it makes sure that the output shows up on the screen immediately and so the use of std::endl isnt preferred; rather we prefer '\n' instead.
    But here in this tutorial, u have written that "When std::cout is used for output, the output may be buffered -- that is, std::cout may not send the text to the output device immediately. Instead, it may opt to “collect output” for a while before writing it out."
    So isnt this statement contradicting with the statement that u made earlier?
    Eagerly waiting for your response..

    • @std::endl flushes the buffer, not @std::cout.

      • Somoshree Datta

        Thanks nascardriver for the reply :)
        In the tutorial named Introduction to iostream: cout,cin and endl, there under the heading of std::endl vs '\n', it is mentioned that : "Using std::endl can be a bit inefficient, as it actually does two jobs: it moves the cursor to the next line, and it “flushes” the output (makes sure that it shows up on the screen immediately). When writing text to the console using std::cout, std::cout usually flushes output anyway (and if it doesn’t, it usually doesn’t matter), so having std::endl flush is rarely important."
        So isnt this a contradiction?

        • No.

          Even if you don't use @std::endl, the buffer will be flushed at some point. Most likely you won't notice a difference between using @std::endl and '\n'.
          @std::endl is bad when you print multiple lines.

          The buffer will be flushed after every line, that's slow. It's enough to flush the buffer once after the last line or let @std::cout take care of it when it wants to.

          All 4 lines can remain in the buffer and then be printed all at once. Or one after the other, whatever @std::cout likes.

  • Gejsi

    Hi! What is the purpose of char variable? Just so we are able to input and output special literals other than integers?

    (Besides memory usage, sunce other data types take more space)

  • Hassan

    Hi everyone,
    here is my simple program to invert the case of an alphabet input by the user.
    please correct me if something is wrong including comments-style(good/bad).

    • * Chars are signed by default. There's no need to write it out.
      * Line 7: You're only checking in ch <= 'Z'. Give it another look.
      * Magic number: 32. Declare a constant or replace it with 'a' - 'A'.
      * Line 12: I'm guessing it'd be more efficient to pass \n as a char, not a string.

      > including comments-style
      I don't like comments that are on the same line as code. This is personal preference.

  • kaworu

    char c = '\78';
    cout << "c="<<c;
    why c=8?

    • \ means escape what comes next. If the next character is a digit, it's interpreted as octal. \7 is an octal 7, which is the bell character ( http://www.asciitable.com/ ). That char is done. You added an extra 8. This 8 is just the character 8, it's not interpreted as a number. You now have to characters in single quotation marks ('\7' and '8'). Behavior is implementation defined. Your compilers appears to ignore the '\7' and just store '8' in @c. Make sure you followed lesson 0.11. Your compiler should have warned you about this.

  • Hassan

    hi everyone,
    suppose i am working on a project where memory management is of paramount importance and i  am only gonna need integers  in the range 0-255, so i chose the type "char".
    Is there a way to treat and manipulates(arithmetically) them as numbers without converting it to short or larger type?

    • Hi Hassan!

      Arithmetic operators may promote their operands to int. You can get around this by writing a wrapper class that handles the casts for you. You should understand this after you finished chapter 10. I can't think of a solution that you could use with what you learned so far.

  • Rai

    So I tried making a char program with if and else statement. But I have a few questions on improving it.

    So I got the if else statement working. If I put a character that isn't in the ASCII table e.g "ø", "Ü" it'll say "Char overflowed.Exiting."

    However I'm having 2 issues!

    1. How could I take as many characters from the user and output all the character's ascii code. For example the user types in "apple" and it'll output all ascii code for each letter. Or will this be covered in another lesson?

    2. If I don't type in 2 characters for std::cout << "Enter a keyboard character: "
    , it will ask the question again! How do I make it so it asks once and will print out as many characters and only ask the question once.

    It will be highly appreciated if anyone can help me out on this. I'm currently looking at other forums to see if I can find a solution.

    • Hi Rai!

      1. You'll need a loop. Loops are covered later.
      2. You could add a bool parameter to @getCharacter and only print the message if the argument is true.

      Notes:
      * Initialize your variables with uniform initialization
      * Your static_cast's don't do what you want them to do. They only check @y. "x, y" is using the comma operator, which evaluates to its last argument, in this case @y. @x is unchecked. You need to check @x and @y separately.
      * It's bad to let your program exit without printing a trailing line feed, because whatever is printed after your program finished will be in the same line.

  • R310

    Hello!
    Why do I get negative 49 for \pi?

    [code]
    Enter a character: π
    � has ASCII code -49

    Process finished with exit code 0
    [\code]

  • MorbidPitaya

    Hey!)

    In which cases (except when space is extremely valuable) is using the unsigned char more useful than, or expected instead of, the other integer data types? Is the use of the unsigned char not dangerous?

    Concerning the direct output of char literals, does the method work with the newest Visual Studio? When compiling, I get a mistake that states <identifier "cout" is undefined>, even though I copied the code line in the tutorial above.

    Thanks in advance!

    • nascardriver

      Hi MorbidPitaya!

      > In which cases (except when space is extremely valuable) is using the unsigned char more useful than, or expected instead of, the other integer data types?
      Bytes, because they range from 0x00 to 0xFF. But they can also be implemented as signed chars.

      > identifier "cout" is undefined
      You either forgot to include <iostream> or you forgot "std::". If that's not it, please share you code.

  • Larry

    If anyone here's attempting to read every character that the person puts inside the "cin", you can use a while true loop to go forever, or use a custom variable to see when cin's buffer is empty.

  • MoAl

    Hi.. I was playing around with the code and I am not understanding the output of the this code:

    I am getting:
    7
    55
    7
    I understand that 55 is the ASCII code for 7, but where is the 7 come from?
    Thanks..

    • Alex

      The result of this code:

      is implementation defined. C++ expects char literals to be one character, but in your case '97' is two. It looks like your compiler is simply discarding the '9' and treating this as if you'd typed '7'.

  • cppLearner

    Consider the following code:

    Is the following statement true:
    In case1 3 is stored as 0000 0000 0000 0011
    and in case2 3 is converted to its ascii value and then that ascii value is stored in binary form, I mean
    '3' --> ascii value 51 --> stored as 0000 0000 0011 0011.
    Thanks in advance.

  • seb

    "If we want to output a char as a number instead of a character"

    "If you’re using a char to hold small integers"

    Is there a reason that someone would use char over a true integer type like int or short?

  • Gabe

    If I make the user enter true or false could I change that value into 1 or 0 to make it work with a boolean and if statement?

    • nascardriver

      Hi Gabe!

      You can use the std::boolalpha flag to tell std::iostream to use true/false instead of 1/0.

Leave a Comment

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