C++ Data Types Explanation
A data type in C++ is a classification of data that determines the type of operations that can be performed on that data. It specifies the size and type of values that can be stored in a variable, and the range of values that can be represented by that variable.
In C++, data types can be classified as follows:
- Primary or Built-in or Fundamental data type.
- Derived data types.
- User-defined data types

Built-in types (C++):
Built-in types define by the C++ language standard and these are built into the compiler. Built-in types are divided into three main categories: integral, floating-point, and void. Letβs see some built-in data types which are frequently used by programmers,
- Integer
- Character
- Boolean
- Floating Point
- Double Floating Point
- void
- Wide Character
Derived types in C++:
Derived data types are derived from Built-in data types or pre-defined data types. Letβs see some derived data types,
- Arrays types.
- Pointers types.
- Reference types.
- function types.
User-defined data types in C++:
C++ language also provides flexibility to the programmer to create their own data types. Letβs see some user-defined types,
- Class.
- Structure.
- Union.
- Enumeration.
- Typedef defined DataType.
Let’s see the basic data types. It size is given according to 32 bit OS.
Data Types | Memory Size | Range |
---|---|---|
char | 1 byte | -128 to 127 |
signed char | 1 byte | -128 to 127 |
unsigned char | 1 byte | 0 to 127 |
short | 2 byte | -32,768 to 32,767 |
signed short | 2 byte | -32,768 to 32,767 |
unsigned short | 2 byte | 0 to 32,767 |
int | 2 byte | -32,768 to 32,767 |
signed int | 2 byte | -32,768 to 32,767 |
unsigned int | 2 byte | 0 to 32,767 |
short int | 2 byte | -32,768 to 32,767 |
signed short int | 2 byte | -32,768 to 32,767 |
unsigned short int | 2 byte | 0 to 32,767 |
long int | 4 byte | |
signed long int | 4 byte | |
unsigned long int | 4 byte | |
float | 4 byte | |
double | 8 byte | |
long double | 10 byte |
Datatype Modifiers in C++:
The modifier modifies the basic integer type. Also, it can be mixed in any order and only one of each group can be present in the type name. They are as follows,
Note: as with all type specifiers, any order is permitted; so, unsigned short int
and short unsigned int
name the same type similarly also unsigned long long int
and long int unsigned long name the same type.
Signedness:
It can further be divided into two categories signed and unsigned.
signed:
The target type will have a signed representation. There are five standard signed integer types: βsigned char
β, βshort intβ
, βint
β, βlong int
β, and βlong long int
β.
Signed data types represent both positive and negative values. They use one bit to represent the sign (positive or negative) of the value and the remaining bits to represent the magnitude of the value. For example, a signed 8-bit integer can represent values ranging from -128 to 127.
unsigned:
Unsigned data types, on the other hand, represent only non-negative values. They use all the bits to represent the magnitude of the value. For example, an unsigned 8-bit integer can represent values ranging from 0 to 255.
They are the following, βunsigned char
β, βunsigned short int
β, βunsigned int
β, βunsigned long int
β, and βunsigned long long int
β.
Here are some other key differences between signed and unsigned data types:
- Arithmetic operations: Arithmetic operations on signed and unsigned data types can have different results. For example, adding a negative value to a signed data type can result in a negative value, while adding a negative value to an unsigned data type will wrap around to the largest possible value.
- Comparison operations: Comparison operations can also have different results. For example, comparing a signed and an unsigned value can result in unexpected results if the signed value is negative.
- Memory usage: Unsigned data types can represent larger values than signed data types using the same number of bits, as they do not need to reserve one bit for the sign.
In general, it’s best to use signed data types unless you specifically need to represent only non-negative values, as this can help avoid unexpected behavior in your code. However, if you need to represent values that are always non-negative, such as indices or sizes, then an unsigned data type may be more appropriate.
See the below example code,
#include <iostream> using namespace std; int main() { signed char ich; unsigned char uch; signed int iint; unsigned int uint; long int lint; unsigned long int ulint; cout<<"Size of signed char "<<sizeof(ich)<<endl; cout<<"Size of usigned char "<<sizeof(uch)<<endl; cout<<"Size of signed int "<<sizeof(iint)<<endl; cout<<"Size of usigned int "<<sizeof(uint)<<endl; cout<<"Size of signed long int "<<sizeof(lint)<<endl; cout<<"Size of unsigned long int "<<sizeof(uint)<<endl; return 0; }
Output:
Size of signed char 1
Size of usigned char 1
Size of signed int 4
Size of usigned int 4
Size of signed long int 4
Size of unsigned long int 4
Note: Overflow for signed arithmetic yields undefined behavior but unsigned arithmetic does not overflow. For more detail, you can check my other post, βsigned vs unsignedβ.
Size:
Following are the size modifiers.
short:
The target type will be optimized for space and will have a width of at least 16 bits.
long:
The target type will have a width of at least 32 bits.
long long:
The target type will have a width of at least 64 bits. (since C++11)
