4.1 — Introduction to fundamental data types

Bits, bytes, and memory addressing

In lesson 1.3 -- Introduction to variables, we talked about the fact that variables are names for a piece of memory that can be used to store information. To recap briefly, computers have random access memory (RAM) that is available for programs to use. When a variable is defined, a piece of that memory is set aside for that variable.

The smallest unit of memory is a binary digit (also called a bit), which can hold a value of 0 or 1. You can think of a bit as being like a traditional light switch -- either the light is off (0), or it is on (1). There is no in-between. If you were to look at a random segment of memory, all you would see is …011010100101010… or some combination thereof.

Memory is organized into sequential units called memory addresses (or addresses for short). Similar to how a street address can be used to find a given house on a street, the memory address allows us to find and access the contents of memory at a particular location.

Perhaps surprisingly, in modern computer architectures, each bit does not get its own unique memory address. This is because the number of memory addresses are limited, and the need to access data bit-by-bit is rare. Instead, each memory address holds 1 byte of data. A byte is a group of bits that are operated on as a unit. The modern standard is that a byte is comprised of 8 sequential bits.

Key insight

In C++, we typically work with “byte-sized” chunks of data.

The following picture shows some sequential memory addresses, along with the corresponding byte of data:

Memory Addressing

As an aside...

Some older or non-standard machines may have bytes of a different size (from 1 to 48 bits) -- however, we generally need not worry about these, as the modern de-facto standard is that a byte is 8 bits. For these tutorials, we’ll assume a byte is 8 bits.

Data types

Because all data on a computer is just a sequence of bits, we use a data type (often called a “type” for short) to tell the compiler how to interpret the contents of memory in some meaningful way. You have already seen one example of a data type: the integer. When we declare a variable as an integer, we are telling the compiler “the piece of memory that this variable uses is going to be interpreted as a non-fractional number”.

When you assign a value to an object, the compiler and CPU take care 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.

As an example, when you give an integer object the value 65, that value is stored in memory as the sequence of bits 0100 0001. When you need that value, those bits are reconstituted back into the integer value 65.

Fortunately, the compiler and CPU take care of converting values into bit sequences (and reconstructing those values from bit sequences again when needed), so you don’t need to worry about that part. All you need to do is pick a data type for your object that best matches your desired use.

Fundamental data types

C++ comes with built-in support for many different data types. These are called fundamental data types, but are often informally called basic types, primitive types, or built-in types.

Here is a list of the fundamental data types, some of which you have already seen:

Types Category Meaning Example
long double
Floating Point a number with a fractional part 3.14159
bool Integral (Boolean) true or false true
char8_t (C++20)
char16_t (C++11)
char32_t (C++11)
Integral (Character) a single character of text ‘c’
long long (C++11)
Integral (Integer) positive and negative whole numbers, including 0 64
std::nullptr_t (C++11) Null Pointer a null pointer nullptr
void Void no type n/a

This chapter is dedicated to exploring these fundamental data types in detail (except std::nullptr_t, which we’ll discuss when we talk about pointers). C++ also supports a number of other more complex types, called compound types. We’ll explore compound types in a future chapter.

Author's note

The terms “integer” and “integral” are similar, but have different meanings. Integers are positive and negative whole numbers, including 0. The term “integral types” (which means “like an integer”) includes all of the boolean, characters, and integer types (and thus is a bit broader in definition). Integral types are named so because they are stored in memory as integers, even though they behave slightly differently.

The _t suffix

Many of the types defined in newer versions of C++ (e.g. std::nullptr_t) use a _t suffix. This suffix means “type”, and it’s a common nomenclature applied to modern types.

If you see something with a _t suffix, it’s probably a type. But many types don’t have a _t suffix, so this isn’t consistently applied.

4.2 -- Void
3.x -- Chapter 3 summary and quiz

74 comments to 4.1 — Introduction to fundamental data types

  • Careena

    I wrote the program like this...
    using namespace std;
    void main()
    int a=5,b(5);
    But when I ran this program errors occured.what's wrong in this program?

    • Mohammad Abouchama

      I don't know if you found the answer by now but I'll help just in case.

      The main() function must have a return type of int. So it should be like this int main(). Whereas yours has void.
      It can have several other forms such as:

      int main(void)
      int main()
      int main(int argc, char *argv[])
      int main(int argc, char ** argv[])

      But all must return an int.
      So basically just replace void with int, and make this statement return 0; as your last statement.

  • Kostas81

    A quick question:

    Alex wrote: "The last mistake is the dangerous case. In this case, the programmer mistakenly tries to initialize both variables by using one assignment statement.

    1 int nValue1, nValue2 = 5; // wrong (nValue1 is uninitialized!)
    3 int nValue1 = 5, nValue2 = 5; // correct

    In the top statement, the nValue1 variable will be left uninitialized, and the compiler will NOT complain. This is a great way to have your program intermittently crash and produce sporadic results."

    But in section 1.3, "A first look at variables (and cin)" Alex had wrote:

    "A variable that has not been assigned a value is called an uninitialized variable. Uninitialized variables are very dangerous because they cause intermittent problems (due to having different values each time you run the program). This can make them very hard to debug. Most modern compilers WILL print warnings at compile-time if they can detect a variable that is used without being initialized."

    And few lines before he wrote:

    "Some newer compilers, such as Visual Studio 2005 Express will pop up a debug error message if you run this program from within the IDE." (He means a program with an uninitialized variable.)

    So, why here the compiler will not complain about the uninitialized variable???
    (And can someone tell me, "wrote" is the past tense for "write" or not? :D)

  • prafull.badyal

    gud..thanks to sir alex

  • Shaun

    so then by making new functions such as:

    int read( int x, int y)
    	return x + y;

    is kind of extra work if we can just declare the variables within the Main() function, and get the same output? for example:

    int main()
    	using namespace std;
    	int x;
    	cout << "enter first number here" << endl;
    	cin >> x;
    	int y;
    	cout << "enter second number here" << endl;
    	cin >> y;
    	cout << x + y << endl;
    	return 0;

    this doesnt require any other functions to add 2 numbers from a user and give a result. but in the chapter 1 comprehension quiz we needed 2 functions to do what this single Main() function can do without the hassle. am i missing something? or does this seem so much easier? or maybe that's why you made this more clear in the next chapter? just want to note, i do understand making a function to do this for us is beneficial for multiple addition problems, but for a single one, i find this is much simpler.

  • AsianBorat

    YES!!!! This is exactly what I was looking for! (I was wondering about the "int nValue1, nValue2 = 5; // wrong (nValue1 is uninitialized!)" bit when I was searching for an answer on google)

    I also learned a whole lot more about declaring ints than from other tutorials.

  • Gigith

    "computers have random access memory (RAM) that is available for program to use."
    That should be "programs" or "the program".

  • Lilwolf

    I have a question...

    I'm learning Computer Science through a college class, and we were taught to declare variables in the header files under the private section with functions under public...

    Why? I'm a little confused and eager to learn, and sadly my professor doesn't seem to be able to explain things too well. Help please!! :)

  • Fluke

    Hi Alex,
    Great tutorial so far!

    A question about declaring variables where they are used.
    I am a bit old-style programmer and i cant find the arguments for declare variables when used to be so good.

    Here is my reasoning (proove me wrong, so i can change my style :)
    Lets see if we have 1000 lines of code. We have a function of 300 lines somewere inside (among other functions).
    If we use function variables more than once inside that function, and they are declared on their first use, isnt it harder, later on, to find out which one is global and which is declared within those 300 lines?
    Or just if we had all function variables just under function name - you can see on first glance which one is there and which one is global?

  • Hi, alex.
    can you tell me when I define an int like

    int i;

    where is the information like the type and the address of i placed?

Leave a Reply

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">