Lesson 4 - More on the C++ type system: Data types
In the previous exercise, Solved tasks for C++ lessons 1-3, we've practiced our knowledge from previous lessons.
Lesson highlights
Are you looking for a quick reference on data types in C++ instead of a thorough-full lesson? Here it is:
Creating variables of basic whole-number data types:
{CPP_CONSOLE}
char a = 15; // can store numbers from -128 to 127
short b = 10000; // -32 768 to 32 767
int c = 500000; // -2 147 483 648 to 2 147 483 647
long d = 10000000000; // large numbers, the range depends on the compiler
cout << (a + b) << endl; // We can use basic arithmetics
cin.get();
{/CPP_CONSOLE}
Creating decimal variables:
{CPP_CONSOLE}
float f = 3.141592f; // single precision
double d = 3.14159265358979; // double precision
cout << f << endl;
cout << d << endl; // note that not all digits are printed to save console space
cin.get();
{/CPP_CONSOLE}
Declaring other built-in data types:
{CPP_CONSOLE}
string s = "This text can be as long as we want";
char a = 'A'; // One character
bool loveCplusPlus = true; // bools are true or false
cout << s << endl;
cout << a << endl;
cout << loveCplusPlus << endl; // bools are printed as 0/1
cin.get();
{/CPP_CONSOLE}
Would you like to learn more? A complete lesson on this topic follows.
In the previous lesson, Solved tasks for C++ lessons 1-3, we learned basic data types of C++
(int
, double
, and string
). In today's
tutorial, we're going to look at them in more detail and explain how to use them
properly. Today is going to be more theoretical, and the next lesson will be
very practical. At the end, we'll make a few simple examples.
C++ recognizes many kinds of datatypes, the basic ones are called fundamental and they're mostly numeric.
Whole-number data types
Let's look at the table of all of the built-in whole-number data types in
C++, notice the int
type, which we're already familiar with.
Data type | Range | Size |
---|---|---|
signed char | -128 to 127 | 8 bits |
unsigned char | 0 to 255 | 8 bits |
short | –32 768 to 32 767 | 16 bits |
unsigned short | 0 to 65 535 | 16 bits |
int | –2 147 483 648 to 2 147 483 647 | 32 bits |
unsigned int | 0 to 4 294 967 295 | 32 bits |
long int | size and range depend on the compiler | |
unsigned long int | size and range depend on the compiler | |
long long long int | size and range depend on the compiler | |
unsigned long long int | size and range depend on the compiler |
Note: The ranges and sizes of data types depend on the compiler you're using and on the system architecture, I've provided values for Visual Studio and 64-bit architecture.
By now, you might be thinking - why do we have so many data types for storing
numbers? The answer is simple, we choose which one to use based on the number's
size. If the number is large, it consumes more memory. For a user's age, we
should select unsigned char
since nobody can live more than
255
years. Imagine a database with millions of users on some
informational system. If we chose int
instead of
unsigned char
, it would occupy four times more space. Conversely,
if we have a function that calculates a factorial, the range of int
would not be enough for us and we'd have to use long long
.
Notice the unsigned
keyword before some of the types. Those
types are almost the same as their "twins" without the unsigned
keyword, however, they don't store negative values. Therefore, we're able to
store a number twice as large in the positive part. The ones that can't store
negative values are called unsigned and the ones that can are called signed
variables (signed in the sense that it "stores" the positive or
negative sign
). We don't have to provide the signed
keyword, the compiler does that by default (the only exception is
char
since it carries other meaning).
Nonetheless, you don't have to think hard about the choice of data type,
we'll use int
almost every time. You have to think about it only in
case the variables are in an array or collection in general, and there are a lot
of them. In that case, it's worth it to consider memory requirements. The tables
I gave here are mainly for the sake of completeness. The already-mentioned
implicit conversion also works between the types, so we can assign an
int
to a long
variable directly, without having to
convert it.
Decimal numbers
For decimal numbers, the choice is simpler. We can only choose between three
data types. They differ in the range of values, and also in precision, i.e. in
the number of decimal places. Double
s are twice as precise as
float
s, which you probably deduced from its name.
Data type | Range | Precision |
---|---|---|
float | +-3.4 * 10−38 to +-3.4 * 1038 | 7 digits |
double | +-1.7 * 10−308 to +-1.7 * 10308 | 15 digits |
long double | +-1.7 * 10−308 to +-1.7 * 10308 | 15 digits |
Note: the long double
type is sometimes the same as
double
or even bigger, however, it's the same in Visual
Studio.
Beware, due to the fact that decimal numbers are stored in your computer in a binary system, there is some precision loss. Although the deviation is almost negligible, if you're programming, e.g. a financial system, it could lead to slight deviations.
When we need to assign a value to a float
variable in the source
code, we have to use the f
suffix:
double d = 2.72; float f = 3.14f;
As the decimal separator in a source code, we use dots, regardless of our OS' regional settings.
Other built-in data types
Let's look at the other data types that C++ offers:
Data type | Range | Size/Precision | Meaning |
---|---|---|---|
char | U+00 to U+ff (0 to 255 or -128 to 127) | 8 bites | character |
wchar_t | U+0000 to U+ffff (0 to 65 535) | 16 bites | "wide" character |
bool | true or false (1 or 0) | 8 bites | logical value |
Char
Char
represents one character, unlike strings, which represents
an entire string
of chars. Characters are declared with apostrophes
in C++:
char c = 'A';
A single, non-array, char
actually belongs in the list of
whole-number variables. It contains a numeric character code, but it seemed more
logical for me to put it here.
Bool
Variables of the bool
type can only contain two values:
true
or false
. We'll use them when we get to
conditions. In a variable of the bool
type, we can store either
true
/false
or a logical expression. Let's make a
simple example:
{CPP_CONSOLE}
bool b = false;
bool expression = (15 > 5);
cout << b << endl;
cout << expression << endl;
cin.get();
{/CPP_CONSOLE}
The program output:
Console application
0
1
We write expressions in parentheses. Notice that the expression applies, i.e.
is equal to true
since 15
really is more than
5
. Going from expressions to conditions isn't a far stretch, but
we'll go into them in the next lesson.
There's still a lot to go over and lots of other data types that we haven't covered. Regardless, there is a time for everything. In the next lesson, Conditions (branching) in the C++ language, we'll introduce conditions and then loops. Then, we'll have enough knowledge to create interesting programs