Variables and Basic Data Types

In C++ we can represent all of our data in the form of variables: pieces of data that are given a certain name. Variables are crucial in programming because they allow the programmer to easily keep track of different pieces of information.

When we create a variable we must also decide which data type it will store, whether that’s a string, an integer, or any of the other data types present in the C++ language. In this page, I’ll go over how to create variables and what data types variables can contain.

Variables in Practice

#include <iostream>
 
int main() {
    int thisIsAVariable = 5;
    std::cout << thisIsAVariable << "\n";
    return 0;
}

The code above should look very similar to our last program, except, this time, we’re printing the value of the variable “thisIsAVariable” (rather than “Hello world!”).

From this, you may see that the structure for creating a variable is the following: [data type] [data name] = [value];. In this case, our variable “thisIsAVariable” is of the int (integer) data type, it has the name “thisIsAVariable”, and its value is 5. Therefore, when running this program, you should see the number 5 printed to the screen.

Note that variable names in C++ are written in “camel case,” meaning that the first word is lowercase and every other word begins with an uppercase letter. Because spaces aren’t allowed in variable names, this makes it easier to read variable names of more than one word

Data Types

C++ has a lot of data types, many of which I’ve never used. Below is a list of the most often-used data types, but you can click here for a more complete list. Please note that the data type sizes and value ranges listed below are the values that you will most often encounter. However, due to limits present in older computers, the size of certain data types in those computers may be smaller. Generally (for our purposes), it is safe to assume that the below table holds true.

Type NameDescriptionSize (in bytes)Range of Values
intAn integer (number without decimal point)4-2,147,483,648 to 2,147,483,647
unsigned intA positive integer40 to 4,294,967,295
boolShort for “boolean”, data that is either true or false1false or true (0 or 1)
charA character or one-byte integer1-128 to 127
unsigned charA character or positive one-byte integer10 to 255
floatA number that can include values after the decimal point4+/- 3.4 * 10^38 (about 7 decimal digits)
doubleA number that can include values after the decimal point (with twice the precision of float)8+/- 1.7 * 10^308 (about 16 decimal digits)

A Note on Chars

Most of the data types above should seem fairly intuitive, but chars may seem a little odd at first. You’d probably expect a char to just hold actual characters, like "a", "b", or "c", rather than numbers. Really, the numbers stored in a char just represent a character by following the ASCII table below.

Focus on the “Decimal” and “Char” columns. The “Hex” column refers to the character’s code in hexadecimal (base 16)

Try it:

#include <iostream>
 
int main() {
    char letterA = 65;
    char alsoLetterA = 'A';
    std::cout << "Letter A expressed with ASCII code: " << letterA << "\n";
    std::cout << "Letter A expressed with its character: " << alsoLetterA << "\n";
    return 0;
}

After running the above code, you should see that a char equal to 65 is displayed in the same way as a char equal to ‘A’. Looking at the "Decimal" and "Char" columns of the ASCII table above, you’ll see that the number 65 does map to an ‘A’. Note that single quotes must be used when writing chars.

Variables in Practice (2)

Try it: Run the code below to see all the different data types in action.

#include <iostream>
 
int main() {
    int a = -120;
    unsigned int b = 200;
    unsigned int c = -20;
    bool d = false;
    bool e = true;
    bool f = 0;
    bool g = 1;
    char h = 'a';
    char i = 85;
    float pi = 3.14;
    double phi = 1.618;

    std::cout << "Integer: " << a << "\n";
    std::cout << "Unsigned integer: " << b << "\n";
    std::cout << "Unsigned integer given negative value: " << c << "\n";
    std::cout << "False boolean (set to false): " << d << "\n";
    std::cout << "True boolean (set to true): " << e << "\n";
    std::cout << "False boolean (set to 0): " << f << "\n";
    std::cout << "True boolean (set to 1): " << g << "\n";
    std::cout << "Character ('a'): " << h << "\n";
    std::cout << "Character (ASCII code 85): " << i << "\n";
    std::cout << "Float: " << pi << "\n";
    std::cout << "Double: " << phi << "\n";

    return 0;
}

One thing to notice is that setting an unsigned variable to a negative value causes the value to “wrap” around to its maximum possible positive value. For example, an unsigned int set equal to -1 becomes 4,294,967,295 (the maximum value for an unsigned int). Set to -2, an unsigned int becomes 4,294,967,294. Because of this, you usually need to ensure that an unsigned variable is only ever set to a positive value.

This behavior begs the question: Why bother with unsigned variables? I often make variables unsigned if I know they will only be equal to positive values. That usually makes it easier for me and others to see what types of values a variable will ever hold. It mostly comes down to personal preference, but it’s usually clearer to be more specific with your data types.

Modifying Variables

After creating a variable, it can also be given a new value at any time. Just note that the data type for a variable should only be written when first creating that variable.

#include <iostream>
 
int main() {
    int x = 25;
    x = 15;
    std::cout << x << "\n";
    return 0;
}

Variables don’t even need to be given an initial value. Just be sure to set the variable equal to something before using it! If you don’t, your program may still work, but it leads to “undefined behavior.” Basically, anything could happen.

#include <iostream>

int main() {
    int x;
    x = 10; //See what happens when this line is removed
    std::cout << x << "\n";
    return 0;
}

Try it: See what happens when printing an integer variable before setting it equal to anything. You’ll likely just see the number 0, but you can never trust that that will always be the case!

Type Casting

If you ever need to change a variable from one data type to another, you can use “type casting.” There are two basic ways to do so (both of which generally do the same thing), shown below:

#include <iostream>

int main() {
    float x = 5.67;
    std::cout << (int) x << "\n";
    std::cout << int(x) << "\n";
    return 0;
}

Program output:

5
5

In this example, we convert x from having a float data type to having an int data type. As you’d expect, doing this conversion removes x‘s decimal component, so it becomes just 5.

By casting char variables to int, we can display a character’s ASCII code:

#include <iostream>

int main() {
    char letterA = 'A';
    std::cout << letterA << "\n";
    std::cout << (int) letterA << "\n";
    return 0;
}

Program output:

A
65

Constants

Using the const keyword in C++, we can mark data as being constant. For example, I may write const float PI = 3.14159;. By doing this, the C++ compiler will generate an error if I ever try to change the constant’s value. (Note that constants’ names are often written in all caps to clearly indicate that they are constants.)

Try it: Create a constant and then try to modify its value. See what happens when compiling your code.

int main() {
    const int PI = 3.14159;
    PI = 5.2; //Invalid
    return 0;
}

Constants are useful because, if you know a value should never change (like pi, for example), you prevent yourself from ever accidentally changing that value in your code. By marking certain values as constant, it also makes it clear to other people reading your code that you don’t want a value to ever change.