5. Types – Modern C++ for Absolute Beginners: A Friendly Introduction to C++ Programming Language and C++11 to C++20 Standards

© Slobodan Dmitrović 2020
S. DmitrovićModern C++ for Absolute Beginnershttps://doi.org/10.1007/978-1-4842-6047-0_5

5. Types

Slobodan Dmitrović1 
(1)
Belgrade, Serbia
 

Every entity has a type. What is a type? A type is a set of possible values and operations. Instances of types are called objects. An object is some region in memory that has a value of particular type (not to be confused with an instance of a class which is also called object).

5.1 Fundamental Types

C++ has some built-in types. We often refer to them as fundamental types. A declaration is a statement that introduces a name into a current scope.

5.1.1 Boolean

Let us declare a variable b of type bool . This type holds values of true and false.
int main()
{
    bool b;
}
This example declares a variable b of type bool. And that is it. The variable is not initialized, no value has been assigned to it at the time of construction. To initialize a variable, we use an assignment operator = followed by an initializer:
int main()
{
    bool b = true;
}
We can also use braces {} for initialization:
int main()
{
    bool b{ true };
}

These examples declare a (local) variable b of type bool and initialize it to a value of true. Our variable now holds a value of true. All local variables should be initialized. Accessing uninitialized variables results in Undefined Behavior, abbreviated as UB. More on this in the following chapters.

5.1.2 Character Type

Type char, referred to as character type, is used to represent a single character. The type can store characters such as 'a', 'Z' etc. The size of a character type is exactly one byte. Character literals are enclosed in single quotes '' in C++. To declare and initialize a variable of type char, we write:
int main()
{
    char c = 'a';
}
Now we can print out the value of our char variable:
#include <iostream>
int main()
{
    char c = 'a';
    std::cout << "The value of variable c is: " << c;
}
Once declared and initialized, we can access our variable and change its value:
#include <iostream>
int main()
{
    char c = 'a';
    std::cout << "The value of variable c is: " << c;
    c = 'Z';
    std::cout << " The new value of variable c is: " << c;
}
The size of the char type in memory is usually one byte. We obtain the size of the type through a sizeof operator:
#include <iostream>
int main()
{
    std::cout << "The size of type char is: " << sizeof(char) << " byte(s)";
}

There are other character types such as wchar_t for holding characters of Unicode character set, char16_t for holding UTF-16 character sets, but for now, let us stick to the type char.

A character literal is a character enclosed in single quotes. Example: 'a', 'A', 'z', 'X', '0' etc.

Every character is represented by an integer number in the character set. That is why we can assign both numeric literals (up to a certain number) and character literals to our char variable:
int main()
{
    char c = 'a';
    // is the same as if we had
    // char c = 97;
}

We can write: char c = 'a'; or we can write char c = 97; which is (probably) the same, as the 'a' character in ASCII table is represented with the number of 97. For the most part, we will be using character literals to represent the value of a char object.

5.1.3 Integer Types

Another fundamental type is int called integer type . We use it to store integral values (whole numbers), both negative and positive:
#include <iostream>
int main()
{
    int x = 123;
    int y = -256;
    std::cout << "The value of x is: " << x << ", the value of y is: " << y;
}
Here we declared and initialized two variables of type int. The size of int is usually 4 bytes. We can also initialize the variable with another variable. It will receive a copy of its value. We still have two separate objects in memory:
#include <iostream>
int main()
{
    int x = 123;
    int y = x;
    std::cout << "The value of x is: " << x << " ,the value of y is: " << y;
    // x is 123
    // y is 123
    x = 456;
    std::cout << "The value of x is: " << x << " ,the value of y is: " << y;
    // x is now 456
    // y is still 123
}

Once we declare a variable, we access and manipulate the variable name by its name only, without the type name.

Integer literals can be decimal, octal, and hexadecimal. Octal literals start with a prefix of 0, and hexadecimal literals begin with a prefix of 0x.
int main()
{
    int x = 10;     // decimal literal
    int y = 012;    // octal literal
    int z = 0xA;    // hexadecimal literal
}

All these variables have been initialized to a value of 10 represented by different integer literals. For the most part, we will be using decimal literals.

There are also other integer types such as int64_t and others, but we will stick to int for now.

5.1.4 Floating-Point Types

There are three floating-point types in C++: float, double, long double, but we will stick to type double (double-precision). We use it for storing floating-point values / real numbers:
#include <iostream>
int main()
{
    double d = 3.14;
    std::cout << "The value of d is: " << d;
}
Some of the floating-point literals can be:
int main()
{
    double x = 213.456;
    double y = 1.;
    double z = 0.15;
    double w = .15;
    double d = 3.14e10;
}

5.1.5 Type void

Type void is a type with no values. Well, what is the purpose of such type if we can not objects of that type? Good question. While we can not have objects of type void, we can have functions of type void. Functions that do not return a value. We can also have a void pointer type marked with void*. More on this in later chapters when we discuss pointers and functions.

5.2 Type Modifiers

Types can have modifiers. Some of the modifiers are signed and unsigned. The signed (the default if omitted) means the type can hold both positive and negative values, and unsigned means the type has unsigned representation. Other modifiers are for the size: short - type will have the width of at least 16 bits, and long - type will have the width of at least 32 bits. Furthermore, we can now combine these modifiers:
#include <iostream>
int main()
{
    unsigned long int x = 4294967295;
    std::cout << "The value of an unsigned long integer variable is: " << x;
}

Type int is signed by default.

5.3 Variable Declaration, Definition, and Initialization

Introducing a name into a current scope is called a declaration. We are letting the world know there is a name (a variable, for example) of some type, from now on in the current scope. In a declaration, we prepend the variable name with a type name. Declaration examples:
int main()
{
    char c;
    int x;
    double d;
}
We can declare multiple names on the same line:
int main()
{
    int x, y, z;
}
If there is an initializer for an object present, then we call it an initialization . We are declaring and initializing an object to a specific value. We can initialize an object in various ways:
int main()
{
    int x = 123;
    int y{ 123 };
    int z = { 123 };
}
A variable definition is setting a value in memory for a name. The definition is making sure we can access and use the name in our program. Roughly speaking, it is a declaration followed by an initialization (for variables) followed by a semicolon. The definition is also a declaration. Definition examples:
int main()
{
    char c = 'a';
    int x = 123;
    double d = 456.78;
}