Topic 7 of 91 2. C++ Fundamentals Interactive Tutorial

C++ Data Types Explained: Primitive, Derived, and User-Defined Types

15 mins read Last updated: 26 Sep 2026 21,400 views

Direct Answer & Core Concept

Data types are one of the basic building blocks of C++ programming. A data type tells the compiler what kind of value a variable can store, such as an integer, decimal number, character, or Boolean value.

For example:

main.cpp
Run Online
int age = 25;
double price = 99.99;
char grade = 'A';
bool isActive = true;

Each variable has a different data type because each stores a different kind of value.

C++ provides several built-in data types and also allows programmers to create more complex types using classes, structures, enumerations, arrays, pointers, references, and other language features.

Detailed Explanation & Mechanics

What Is a Data Type in C++?

A data type defines the kind of value that a variable can hold.

For example:

Here:

  • int is the data type.

  • age is the variable.

  • 30 is the value.

Another example:

main.cpp
Run Online
double temperature = 36.5;

Here:

  • double is the data type.

  • temperature is the variable.

  • 36.5 is the value.

The data type helps the compiler determine how the value should be represented and what operations can be performed on it.


Why Are Data Types Important?

Data types are important because computers store different kinds of information differently.

For example:

stores an integer.

While:

stores a floating-point number.

And:

stores a Boolean value.

Choosing an appropriate data type helps make programs:

  • Correct

  • Efficient

  • Easier to understand

  • Easier to maintain

  • More predictable


Main Categories of C++ Data Types

C++ data types can broadly be organized into three groups:

Architecture Diagram
C++ Data Types
│
├── Fundamental Types
│   ├── Integer
│   ├── Floating-point
│   ├── Character
│   ├── Boolean
│   └── void
│
├── Derived Types
│   ├── Arrays
│   ├── Pointers
│   ├── References
│   └── Functions
│
└── User-Defined Types
    ├── struct
    ├── class
    ├── union
    ├── enum
    └── Type aliases

The exact classification can vary slightly depending on how a C++ reference groups language types, but this three-part model is useful for beginners.


1. Fundamental Data Types

Fundamental types are the basic types provided directly by the C++ language.

Important fundamental types include:

  • bool

  • char

  • char8_t

  • char16_t

  • char32_t

  • wchar_t

  • short

  • int

  • long

  • long long

  • float

  • double

  • long double

  • void

There are also signed and unsigned integer variations.


Integer Data Types

Integer types store whole numbers without a fractional part.

Examples:

main.cpp
Run Online
int age = 25;
int score = 100;
int temperature = -5;

Integer values can be:

  • Positive

  • Negative

  • Zero

Examples:


The int Data Type

int is one of the most commonly used integer types.

Example:

Another example:

main.cpp
Run Online
int numberOfStudents = 50;

For most ordinary whole-number calculations, int is a good default.

The exact size of int is implementation-defined, although on modern mainstream systems it is commonly 32 bits.

Do not assume that every C++ implementation has exactly the same integer sizes.


short Integer Type

short is an integer type that is commonly used when a smaller integer range is sufficient.

Example:

A short is at least 16 bits wide.

Its exact size depends on the implementation.


long Integer Type

The long type can represent a wider range than short, but its size differs between platforms.

Example:

main.cpp
Run Online
long population = 1000000;

The size of long is platform-dependent.

For example, common systems may use different sizes for long on Windows and Linux.

This is one reason portable C++ programs should avoid assuming exact sizes when they matter.


long long

long long is commonly used when a larger integer range is required.

Example:

main.cpp
Run Online
long long distance = 9000000000LL;

It is guaranteed to be at least 64 bits wide.

The LL suffix tells the compiler that the integer literal is intended to have long long type.


Signed and Unsigned Integers

Integer types can generally be signed or unsigned.

A signed integer can represent negative and positive values.

For example:

An unsigned integer represents non-negative values.

Example:

Unsigned integer types have no negative range and therefore provide a larger positive range for the same number of value bits.

Use unsigned types when the non-negative nature of a value is meaningful, rather than automatically replacing every integer with unsigned.


Integer Type Comparison

A simplified comparison is:

TypeTypical use
shortSmaller integer values
intGeneral-purpose integers
longPlatform-dependent larger integer range
long longVery large integer values
unsigned intNon-negative integer values

The exact ranges should be checked for the target implementation when portability matters.


Floating-Point Data Types

Floating-point types represent numbers that can contain fractional values.

Examples:

main.cpp
Run Online
float temperature = 36.5f;
double price = 199.99;
long double value = 12345.6789L;

The main floating-point types are:

  • float

  • double

  • long double


float

float is a single-precision floating-point type.

Example:

main.cpp
Run Online
float temperature = 36.5f;

The f suffix indicates a float literal.

For example:

Without the suffix, a decimal floating-point literal such as 10.5 is normally of type double.


double

double provides at least as much precision as float and is commonly used for general floating-point calculations.

Example:

For many applications, double is the standard choice for ordinary floating-point calculations.


long double

long double is an extended floating-point type.

Example:

main.cpp
Run Online
long double value = 123456.789L;

Its precision and representation are implementation-dependent.

It can provide more precision than double on some platforms, but not necessarily on all platforms.


Floating-Point Example

main.cpp
Run Online
#include <iostream>

int main() {
    float height = 5.8f;
    double price = 999.99;

    std::cout << height << "\n";
    std::cout << price << "\n";

    return 0;
}

Output:


Character Data Types

C++ provides character types for representing characters.

The most familiar type is:

Example:

Character literals use single quotes:

This is different from a string:

which uses double quotes.


char

A char is a distinct fundamental type that is commonly used to store a character from the ordinary character set.

Example:

You can also use it with output:

Output:


Character Types for Unicode and Wide Characters

C++ also provides:

main.cpp
Run Online
wchar_t
char8_t
char16_t
char32_t

These types serve different character and encoding-related purposes.

For example:

main.cpp
Run Online
char16_t symbol = u'A';
char32_t value = U'A';

char8_t is associated with UTF-8 code units.

When working with text, remember that a character type and a complete Unicode string are not necessarily the same thing. Unicode text can involve multiple code units and more complex encoding considerations.


Boolean Data Type

The bool type stores a logical value.

It has two values:

Example:

main.cpp
Run Online
bool isLoggedIn = true;
bool isAdmin = false;

Boolean values are frequently used with conditions.

main.cpp
Run Online
if (isLoggedIn) {
    std::cout << "Welcome!";
}

true and false

C++ represents Boolean values as:

Example:

main.cpp
Run Online
bool hasPermission = true;

std::cout << hasPermission;

By default, this commonly prints:

and:

main.cpp
Run Online
bool hasPermission = false;

commonly prints:

You can use std::boolalpha if you want textual output:

main.cpp
Run Online
#include <iostream>

int main() {
    bool isReady = true;

    std::cout << std::boolalpha << isReady;

    return 0;
}

Output:


The void Type

void represents the absence of a value.

It is commonly used with functions that do not return a value.

Example:

main.cpp
Run Online
void showMessage() {
    std::cout << "Hello";
}

The function performs an action but does not return a value.

You cannot normally declare an ordinary variable of type void:


Derived Data Types

Derived types are constructed from or related to other types.

Common examples include:

  • Arrays

  • Pointers

  • References

  • Function types


Arrays

An array stores multiple elements of the same type.

Example:

This creates an array capable of storing five int values.

You can initialize it:

main.cpp
Run Online
int numbers[5] = {
  10, 20, 30, 40, 50
}
;

Access an element using an index:

Output:


Arrays of Different Data Types

Arrays can contain different element types depending on the declaration.

Integer array:

main.cpp
Run Online
int numbers[3] = {
  1, 2, 3
}
;

Floating-point array:

main.cpp
Run Online
double prices[3] = {
  10.5, 20.5, 30.5
}
;

Character array:

main.cpp
Run Online
char letters[3] = {
  'A', 'B', 'C'
}
;

The array's element type determines what kind of values it stores.


Pointers

A pointer stores the address of another object or function, depending on its type.

Example:

main.cpp
Run Online
int age = 25;
int* ptr = &age;

Here:

main.cpp
Run Online
age
↓
25

ptr
↓
address of age

The * in:

indicates a pointer type.

The & in:

obtains the address of age.

Pointers are an important part of C++, particularly for low-level programming, dynamic memory, data structures, and interacting with APIs.


References

A reference provides another name, or alias, for an existing object.

Example:

main.cpp
Run Online
int age = 25;
int& reference = age;

Now reference refers to age.

For example:

main.cpp
Run Online
reference = 30;

std::cout << age;

Output:

References are commonly used for function parameters and returning or accessing existing objects without copying them.


Function Types

Functions also have types based on their return type and parameter types.

For example:

main.cpp
Run Online
int add(int a, int b) {
    return a + b;
}

This function takes two int parameters and returns an int.

Another function:

main.cpp
Run Online
double calculate(double value) {
    return value * 2;
}

takes a double and returns a double.

Functions can therefore be understood as having their own function type.


User-Defined Data Types

C++ allows programmers to create their own types.

Common user-defined mechanisms include:

  • struct

  • class

  • union

  • enum

  • Type aliases

These are especially important when developing larger applications.


Structures

A structure groups related values together.

Example:

main.cpp
Run Online
struct Person {
    std::string name;
    int age;
};

You can create an object:

main.cpp
Run Online
Person person;
person.name = "Rahul";
person.age = 30;

A structure is useful when several pieces of data logically belong together.


Classes

A class is a user-defined type that can combine data and functions.

Example:

main.cpp
Run Online
class Car {
public:
    std::string brand;
    int year;

    void display() {
        std::cout << brand << " " << year;
    }
};

You can create an object:

main.cpp
Run Online
Car car;
car.brand = "Toyota";
car.year = 2025;

Classes are one of the foundations of object-oriented programming in C++.


Enumerations

An enumeration defines a set of named values.

Example:

main.cpp
Run Online
enum class Color {
    Red,
    Green,
    Blue
};

You can use it like this:

main.cpp
Run Online
Color favorite = Color::Blue;

Scoped enumerations using enum class are generally preferable to traditional unscoped enums when you want stronger type safety and clearer names.


Traditional enum

C++ also supports an unscoped enumeration:

main.cpp
Run Online
enum Day {
    Monday,
    Tuesday,
    Wednesday
};

You can then write:

However, enum class is often a better modern choice because its enumerator names remain scoped.


Type Aliases

C++ allows you to create an alternative name for an existing type.

Using using:

main.cpp
Run Online
using Age = int;

Age age = 25;

Here, Age is an alias for int.

You can also use:

main.cpp
Run Online
using Price = double;

Price productPrice = 99.99;

Type aliases can make complex declarations easier to understand.


typedef

C++ also supports the older typedef syntax:

main.cpp
Run Online
typedef int Age;

Age age = 30;

Modern C++ code often prefers:

because the using syntax is easier to read and works naturally with templates.


std::string and Data Types

Beginners often expect string to be one of C++'s fundamental data types.

It is not.

std::string is a class provided by the C++ standard library.

Example:

main.cpp
Run Online
#include <string>

std::string name = "Alex";

So:

is a fundamental type, while:

is a standard library class type.

This distinction becomes more important as you learn the C++ type system.


Type Modifiers

C++ provides modifiers that can change certain fundamental types.

Common modifiers include:

  • signed

  • unsigned

  • short

  • long

For example:

main.cpp
Run Online
unsigned int count;
long long population;
short value;

These modifiers affect the range or representation of applicable integer types.


sizeof Operator

The sizeof operator tells you the size of a type or object in bytes.

Example:

main.cpp
Run Online
#include <iostream>

int main() {
    std::cout << sizeof(int) << "\n";
    std::cout << sizeof(double) << "\n";
    std::cout << sizeof(char) << "\n";

    return 0;
}

The exact output depends on the implementation.

On many modern systems, you may commonly see something like:

But portable C++ code should not assume these values universally.


Checking the Size of a Variable

You can also use sizeof with a variable:

main.cpp
Run Online
int age = 25;

std::cout << sizeof(age);

The result is the size of the object in bytes.

This can be useful when learning about memory and data representation.


Data Type Examples

Here is a simple program using several common types:

main.cpp
Run Online
#include <iostream>
#include <string>

int main() {
    int age = 35;
    double salary = 45000.50;
    char grade = 'A';
    bool employed = true;
    std::string name = "Alex";

    std::cout << "Name: " << name << "\n";
    std::cout << "Age: " << age << "\n";
    std::cout << "Salary: " << salary << "\n";
    std::cout << "Grade: " << grade << "\n";
    std::cout << "Employed: " << std::boolalpha << employed << "\n";

    return 0;
}

Possible output:

main.cpp
Run Online
Name: Alex
Age: 35
Salary: 45000.5
Grade: A
Employed: true

Choosing the Right C++ Data Type

Use a type that accurately represents the data you need.

Whole numbers

Use:

for ordinary integer values.

For larger ranges:

may be appropriate.

Decimal numbers

Use:

for many general-purpose floating-point calculations.

Single characters

Use:

when an individual ordinary character is appropriate.

True or false

Use:

for logical conditions.

Text

Use:

for normal C++ strings.

Grouped data

Use:

or:

when several related values belong together.


Fixed-Width Integer Types

When exact integer widths matter, C++ provides fixed-width integer types through:

Examples include:

main.cpp
Run Online
std::int8_t
std::int16_t
std::int32_t
std::int64_t

and unsigned versions:

main.cpp
Run Online
std::uint8_t
std::uint16_t
std::uint32_t
std::uint64_t

For example:

main.cpp
Run Online
std::int32_t userId = 1001;

These types are useful when a program needs a specific integer width, such as when working with binary files, network protocols, hardware, or serialized data.

They are not guaranteed to exist on an implementation if the implementation has no corresponding exact-width type.


Data Types and Memory

Different types generally require different amounts of storage.

For example, an int usually requires more storage than a char, while a double commonly requires more storage than a float.

However, exact object sizes are implementation-dependent.

You can check them using:

For example:

main.cpp
Run Online
std::cout << sizeof(char) << "\n";
std::cout << sizeof(int) << "\n";
std::cout << sizeof(double) << "\n";

Understanding data sizes becomes particularly useful when working with:

  • Large arrays

  • Embedded systems

  • Network protocols

  • Binary files

  • Performance-sensitive applications

  • Low-level programming


Data Type Conversion

C++ allows values to be converted between different types.

For example:

main.cpp
Run Online
int number = 10;
double result = number;

The integer can be converted to a double.

You can also explicitly request a conversion:

main.cpp
Run Online
double price = 99.99;
int rounded = static_cast<int>(price);

The resulting rounded value is:

The fractional part is discarded during this conversion.

Type conversion deserves careful attention because some conversions can lose information.


Common Data Type Mistakes

Using int for Decimal Values

Incorrect for preserving the decimal part:

The fractional portion cannot be represented by an int.

Use:

instead.


Confusing Character and String Literals

Character:

String:

The first uses single quotes, while the second uses double quotes.


Assuming All Types Have the Same Size Everywhere

Avoid assumptions such as:

main.cpp
Run Online
int is always exactly 4 bytes
long is always exactly 8 bytes

C++ specifies minimum ranges and relationships, while exact sizes can depend on the implementation.

Use sizeof or fixed-width types when exact representation matters.


Using Floating Point for Exact Money Representation

A double can be useful for many calculations, but binary floating-point numbers cannot represent every decimal fraction exactly.

For financial applications where exact decimal behavior is required, use an appropriate decimal or integer-based design rather than assuming double provides exact currency arithmetic.


Fundamental vs Derived vs User-Defined Types

The three categories can be summarized as follows:

CategoryExamplesPurpose
Fundamentalint, double, char, boolBasic values
DerivedArrays, pointers, references, functionsBuilt from or related to other types
User-definedstruct, class, enum, unionCreate custom data models

A modern C++ program commonly uses all three categories together.


Real-World Example

Consider an employee record:

main.cpp
Run Online
#include <string>

struct Employee {
    int id;
    std::string name;
    double salary;
    bool active;
};

Here we combine different types:

Architecture Diagram
Employee
│
├── id      → int
├── name    → std::string
├── salary  → double
└── active  → bool

This is one of the main advantages of user-defined types: you can model real-world concepts using meaningful data structures.


Best Practices for C++ Data Types

1. Choose the type based on meaning

If a value represents true or false, use:

instead of an integer.

2. Prefer clear types

Use:

rather than an unnecessarily complicated type when a simple integer is sufficient.

3. Consider portability

Do not assume implementation-specific type sizes when portability matters.

4. Use fixed-width integers when required

Use:

or:

when an exact width is part of the requirement.

5. Avoid unnecessary conversions

Conversions can sometimes lose information.

6. Use double thoughtfully

Floating-point values are approximate representations and should not automatically be treated as exact decimal values.

7. Use meaningful user-defined types

If several values belong together, a struct or class can make the program easier to understand.


Frequently Asked Questions

What are data types in C++?

Data types specify what kind of value an object or variable represents. Examples include int, double, char, and bool.

What are the basic data types in C++?

Common fundamental types include bool, char, integer types such as int, and floating-point types such as float and double. C++ also provides void and several character and integer variations.

What is the difference between primitive and derived data types in C++?

Fundamental types are basic types provided by the language, such as int and double. Derived types include constructs such as arrays, pointers, references, and function types.

What are user-defined data types in C++?

User-defined types allow programmers to create their own data structures. Common examples include struct, class, union, and enum.

What data type is used for whole numbers in C++?

int is commonly used for ordinary whole numbers. Larger integer types such as long long can be used when a larger range is required.

What data type is used for decimal numbers?

float, double, and long double are floating-point types. double is a common general-purpose choice.

What is the difference between char and string in C++?

char represents a single character, while std::string is a standard library class used to represent a sequence of characters.

What is bool in C++?

bool is a Boolean type with two values:

It is commonly used for conditions and logical state.

What does sizeof do in C++?

sizeof returns the size, in bytes, of a type or object.

Example:

The result depends on the C++ implementation.

What is std::int32_t?

std::int32_t is an optional fixed-width signed integer type provided by <cstdint> when the implementation supports an integer type with exactly 32 bits.

Is double always 8 bytes?

No. Although 8 bytes is common on modern systems, C++ does not universally require double to be exactly 8 bytes.

Is int always 4 bytes?

No. Four bytes is common, but the C++ standard does not require int to have exactly that size on every implementation.

Suggested Graphic Design

Create a clean educational infographic titled:

“C++ Data Types Explained”

Use a three-level tree:

Architecture Diagram
                    C++ DATA TYPES
                          │
          ┌───────────────┼────────────────┐
          │               │                │
    FUNDAMENTAL         DERIVED       USER-DEFINED
          │               │                │
   ┌──────┼──────┐    ┌───┼────┐      ┌────┼─────┐
   │      │      │    │   │    │      │    │     │
  int   double   bool array pointer reference struct class
   │      │      │
  char  float   void

Add short examples underneath:

main.cpp
Run Online
int age = 25;
double price = 99.99;
char grade = 'A';
bool active = true;

Runnable Code Example: C++ Data Types

C++20 / C++23
main.cpp
Run Online
#include <iostream>
#include <cstdint>

struct SensorReading {
    uint64_t timestampMs;
    float temperature;
    bool active;
};

int main() {
    int count = 100;
    double voltage = 5.04;
    char channel = 'C';

    uint32_t baudRate = 115200;
    int& refCount = count;
    double* ptrVolt = &voltage;

    SensorReading sr{1700000000000ULL, 23.4f, true};

    std::cout << "Count (int size): " << sizeof(count) << " bytes
";
    std::cout << "Voltage (double size): " << sizeof(voltage) << " bytes
";
    std::cout << "SensorReading struct size: " << sizeof(sr) << " bytes
";
    return 0;
}

Common C++ Technical Interview Questions & Answers

Interview Prep
Q

Q: What is the difference between float and double in C++?

A: float is a 32-bit single precision IEEE 754 type (~7 decimal digits), whereas double is a 64-bit double precision type (~15-17 decimal digits).
Q

Q: Why should developers use fixed-width types?

A: Standard types like int and long vary across platforms. Using int32_t or uint64_t guarantees identical bit-widths and binary layout across compilers and architectures.

Key Takeaways, Modern Best Practices & Idioms

C++ Best Practices & Production Rules

1. Use fixed-width types (uint32_t, int64_t) for binary serialization and low-level protocols. 2. Initialize primitive types immediately to avoid uninitialized memory reads. 3. Use size_t for array indexing and collection sizes.