How to Create a Variable in C++: A Visual, Hands-On Guide
Learn C++ variables visually: declaring and initializing, the main types (int, double, bool, char, std::string), how big each one is, integer division, overflow, decimal precision, brace initialization, auto, const, naming rules, real compiler messages, and exercises with answers.

On this page
A program that can't remember anything isn't very useful. A game needs to remember your score, a shop needs to remember what's in your cart, and a calculator needs to remember the numbers you typed. In C++, you remember things with variables.
In this guide you'll create variables of every basic type, see how much memory each one takes, and run into the classic surprises: whole-number division, numbers that overflow, decimals that aren't quite exact, and variables used before they get a value. Along the way you'll read real compiler messages, and you'll finish with exercises.
All outputs below come from real runs with GCC 14.1 (g++ -std=c++20) on 64-bit Windows. New to C++? Start with Writing Your First Program in C++.
A variable is a labeled box

To create a variable you write its type, then its name, and usually an initial value:
1#include <iostream>
2#include <string>
3
4int main() {
5 int age = 35;
6 double height = 1.75;
7 bool isStudent = true;
8 char grade = 'A';
9 std::string name = "Roger";
10
11 std::cout << name << " is " << age << " years old and " << height << " m tall.\n";
12 std::cout << "Grade: " << grade << "\n";
13 std::cout << "Student? " << isStudent << "\n";
14 return 0;
15}Roger is 35 years old and 1.75 m tall.
Grade: A
Student? 1intholds whole numbers: 35, -7, 2024.doubleholds numbers with a decimal point: 1.75, -0.5, 3.14159.boolholdstrueorfalse. It prints as1or0(more on that below).charholds a single character, written in single quotes:'A'.std::stringholds text, written in double quotes. It needs#include <string>.
The type matters because C++ is statically typed: once a variable is an int, it's an int forever, and the compiler checks every use of it.
Declaring, assigning and changing
You can declare a variable first and give it a value later, then change it as often as you like. The = sign means "store this value", not "is equal to" (checking equality is ==):
1#include <iostream>
2
3int main() {
4 int score;
5 score = 10;
6 std::cout << "Start: " << score << "\n";
7
8 score = score + 5;
9 std::cout << "After a bonus: " << score << "\n";
10
11 score += 20;
12 score -= 3;
13 score *= 2;
14 std::cout << "After more changes: " << score << "\n";
15
16 score++;
17 std::cout << "Plus one: " << score << "\n";
18 return 0;
19}1Start: 10
2After a bonus: 15
3After more changes: 64
4Plus one: 65score = score + 5 reads the current value, adds 5, and stores the result back. The compound assignments +=, -=, *= and /= are shortcuts for exactly that, and ++ adds one.
Always give a variable a value
A variable that's declared but never given a value holds whatever bits happened to be in that memory: garbage. Reading it is a bug, and the compiler warns you if warnings are on:
1#include <iostream>
2
3int main() {
4 int total;
5 total = total + 10;
6 std::cout << total << "\n";
7 return 0;
8}1$ g++ -std=c++20 -Wall -Wextra uninit.cpp -o uninit
2uninit.cpp: In function 'int main()':
3uninit.cpp:5:11: warning: 'total' is used uninitialized [-Wuninitialized]
4 5 | total = total + 10;
5 | ~~~~~~^~~~~~~~~~~~
6uninit.cpp:4:9: note: 'total' was declared here
7 4 | int total;
8 | ^~~~~The program still builds, but what it prints is unpredictable. The fix is a habit: initialize every variable when you declare it, as in int total = 0;.
How big is each type?
Each type uses a fixed number of bytes, and that limits what it can hold. The sizeof operator tells you a type's size, and std::numeric_limits its range:
1#include <iostream>
2#include <limits>
3#include <string>
4
5int main() {
6 std::cout << "bool: " << sizeof(bool) << " byte\n";
7 std::cout << "char: " << sizeof(char) << " byte\n";
8 std::cout << "short: " << sizeof(short) << " bytes, up to " << std::numeric_limits<short>::max() << "\n";
9 std::cout << "int: " << sizeof(int) << " bytes, up to " << std::numeric_limits<int>::max() << "\n";
10 std::cout << "long: " << sizeof(long) << " bytes, up to " << std::numeric_limits<long>::max() << "\n";
11 std::cout << "long long: " << sizeof(long long) << " bytes, up to " << std::numeric_limits<long long>::max() << "\n";
12 std::cout << "float: " << sizeof(float) << " bytes, about " << std::numeric_limits<float>::digits10 << " exact digits\n";
13 std::cout << "double: " << sizeof(double) << " bytes, about " << std::numeric_limits<double>::digits10 << " exact digits\n";
14 std::cout << "std::string: " << sizeof(std::string) << " bytes (plus the text, if it's long)\n";
15 return 0;
16}1bool: 1 byte
2char: 1 byte
3short: 2 bytes, up to 32767
4int: 4 bytes, up to 2147483647
5long: 4 bytes, up to 2147483647
6long long: 8 bytes, up to 9223372036854775807
7float: 4 bytes, about 6 exact digits
8double: 8 bytes, about 15 exact digits
9std::string: 32 bytes (plus the text, if it's long)
Two things stand out:
- An
inttops out at 2,147,483,647, a bit over 2 billion. Fine for ages and scores, not for the world's population (about 8 billion). longis 4 bytes on Windows but 8 bytes on 64-bit Linux and macOS. The C++ standard only sets minimums, so sizes can differ between systems. When you need an exact size, uselong long(at least 8 bytes) or the fixed-width types likestd::int64_tfrom<cstdint>.
Surprises with numbers
Whole-number division
When both sides of / are integers, C++ does integer division and throws away the remainder. % gives the remainder:
1#include <iostream>
2
3int main() {
4 int pizzas = 7;
5 int people = 2;
6 std::cout << "Each gets " << pizzas / people << " whole pizzas\n";
7 std::cout << "Left over: " << pizzas % people << "\n";
8 std::cout << "Exact share: " << static_cast<double>(pizzas) / people << "\n";
9 return 0;
10}Each gets 3 whole pizzas
Left over: 1
Exact share: 3.5static_cast<double>(pizzas) converts the value to a double for that calculation, so the division keeps the decimals.
Numbers that don't fit
Try to store 3 billion in an int:
1#include <iostream>
2
3int main() {
4 int tooBig = 3000000000;
5 long long bigEnough = 3000000000;
6 std::cout << tooBig << "\n";
7 std::cout << bigEnough << "\n";
8 return 0;
9}-1294967296
3000000000
No error, and not even a warning with -Wall -Wextra: the value silently wraps around to a negative number. Choose a type that's big enough for your data. (Overflowing an int during arithmetic, like adding 1 to the maximum, is even worse: it's undefined behavior, meaning the program can do anything.)
Decimals aren't exact
double stores numbers in binary, and most decimal fractions, like 0.1, can't be written exactly in binary, just as 1/3 can't be written exactly in decimal:
1#include <iomanip>
2#include <iostream>
3
4int main() {
5 double sum = 0.1 + 0.2;
6 std::cout << sum << "\n";
7 std::cout << std::setprecision(17) << sum << "\n";
8 std::cout << (sum == 0.3) << "\n";
9
10 float third = 1.0f / 3;
11 double betterThird = 1.0 / 3;
12 std::cout << std::setprecision(10) << third << " vs " << betterThird << "\n";
13 return 0;
14}10.3
20.30000000000000004
30
40.3333333433 vs 0.3333333333
std::cout rounds to 6 significant digits by default, which hides the error; std::setprecision(17) shows it. Two lessons: use double rather than float unless you have a reason, and don't compare decimals with ==; check that they're close instead. (For money, programs usually count whole cents in an integer.)
bool and char are numbers in disguise
1#include <iostream>
2
3int main() {
4 bool isOpen = true;
5 std::cout << isOpen << "\n";
6 std::cout << std::boolalpha << isOpen << "\n";
7
8 char letter = 'A';
9 std::cout << letter << " has code " << static_cast<int>(letter) << "\n";
10 char next = letter + 1;
11 std::cout << "The next letter is " << next << "\n";
12 return 0;
13}11
2true
3A has code 65
4The next letter is BA bool prints as 1 or 0 unless you send std::boolalpha to the stream first. A char is really a small number (65 is the code for A in ASCII), so you can do arithmetic with it.
Ways to initialize
C++ has several initialization styles. The two you'll see most:
1#include <iostream>
2
3int main() {
4 int withEquals = 3.7;
5 int withBraces{42};
6 double ratio{0.5};
7 std::cout << withEquals << " " << withBraces << " " << ratio << "\n";
8 return 0;
9}3 42 0.5The = version quietly chopped 3.7 down to 3. Brace initialization { } refuses to lose information like that, so a mistake becomes a compiler error instead of a silent bug:
1int main() {
2 int score{3.7};
3 return score;
4}1narrow.cpp: In function 'int main()':
2narrow.cpp:2:15: error: narrowing conversion of '3.7000000000000002e+0' from 'double' to 'int' [-Wnarrowing]
3 2 | int score{3.7};
4 | ^~~That's a narrowing conversion error. (Notice the compiler printing 3.7 as 3.7000000000000002: the decimal problem again!) Many modern style guides recommend braces for exactly this reason.
Letting the compiler pick: auto
With auto, the compiler figures out the type from the initial value:
1#include <iostream>
2#include <string>
3
4int main() {
5 auto count = 10;
6 auto price = 4.99;
7 auto ready = false;
8 auto title = std::string("C++ Variables");
9 std::cout << count << " items at " << price << " each\n";
10 std::cout << title << ", ready: " << std::boolalpha << ready << "\n";
11 return 0;
12}10 items at 4.99 each
C++ Variables, ready: falsecount is an int, price a double, ready a bool and title a std::string. The variable is still strictly typed; you just don't spell the type out. Note that auto title = "C++ Variables"; without std::string(…) would make a plain C-style character array instead of a std::string, one reason to use auto thoughtfully.
Values that never change: const
Mark a variable const when its value should never change after it's set. The compiler then refuses any attempt to change it:
1int main() {
2 const double pi = 3.14159;
3 pi = 3;
4 return 0;
5}1constant.cpp: In function 'int main()':
2constant.cpp:3:8: error: assignment of read-only variable 'pi'
3 3 | pi = 3;
4 | ~~~^~~Use const generously: it documents your intent and turns accidental changes into compile errors. (For values known at compile time, constexpr goes one step further and guarantees the value is computed while compiling.)
Naming your variables

The rules:
- Use letters, digits and underscores, starting with a letter or underscore.
- No spaces, no symbols like
-or$, and no keywords (int,class,return,new…). - Names are case-sensitive:
score,ScoreandSCOREare three different variables.
Break a rule and the compiler stops you:
1int main() {
2 int 2ndPlace = 2;
3 return 0;
4}1badname.cpp: In function 'int main()':
2badname.cpp:2:9: error: expected unqualified-id before numeric constant
3 2 | int 2ndPlace = 2;
4 | ^~~~~~~~Beyond the rules, choose descriptive names. secondsElapsed tells the next reader (often you, a month later) exactly what it holds; s doesn't. The two common styles are camelCase and snake_case; pick one and stay consistent.
Your turn: practice
Try these before peeking at the answers. Compile each with g++ -std=c++20 -Wall -Wextra.
Exercise 1: Predict the output (warm-up). What does this print?
1#include <iostream>
2
3int main() {
4 int apples = 10;
5 int friends = 4;
6 apples -= 2;
7 std::cout << apples / friends << " " << apples % friends << "\n";
8 double average = apples / friends;
9 std::cout << average << "\n";
10 return 0;
11}Exercise 2: Swap two values. Given int left = 3; and int right = 8;, swap their values so that left is 8 and right is 3, then print them. (Hint: you'll need a third variable.)
Exercise 3: Circle calculator. Read a radius (a whole number) and print the circle's area and circumference, using a const double pi = 3.14159;.
Exercise 4: Seconds to hours. Read a number of seconds and print it as hours, minutes and seconds. For example, 3725 seconds is 1 h 2 min 5 s.
Exercise 5: Fix the program (challenge). This should print the price of 3 tickets at 12.50 each and the number of seats left out of 150, but it has three problems. Find them.
1#include <iostream>
2
3int main() {
4 const int seats = 150;
5 int ticketPrice{12.50};
6 int tickets = 3;
7 seats = seats - tickets;
8 std::cout << "Total: " << tickets * ticketPrice << "\n";
9 std::cout << "Seats left: " << seats << "\n";
10 return 0;
11}Quick quiz
- What are the three parts of
int age = 35;? - What's the difference between
=and==? - Why does
7 / 2give 3 in C++? - Why is
int score{3.7};a compile error butint score = 3.7;isn't? - What does
constdo?
Answers
Exercise 1: After apples -= 2, apples is 8. 8 / 4 is 2 with remainder 0. The trap is the last line: apples / friends is computed as integer division first (giving 2), and only then stored in the double:
1#include <iostream>
2
3int main() {
4 int apples = 10;
5 int friends = 4;
6 apples -= 2;
7 std::cout << apples / friends << " " << apples % friends << "\n";
8 double average = apples / friends;
9 std::cout << average << "\n";
10 return 0;
11}2 0
2Exercise 2: Save one value before overwriting it:
1#include <iostream>
2
3int main() {
4 int left = 3;
5 int right = 8;
6 int saved = left;
7 left = right;
8 right = saved;
9 std::cout << "left = " << left << ", right = " << right << "\n";
10 return 0;
11}left = 8, right = 3(The standard library also has std::swap(left, right) in <utility>.)
Exercise 3: The radius is an int, but multiplying by the double pi makes the results doubles:
1#include <iostream>
2
3int main() {
4 const double pi = 3.14159;
5 int radius = 0;
6 std::cout << "Radius: ";
7 std::cin >> radius;
8 double area = pi * radius * radius;
9 double circumference = 2 * pi * radius;
10 std::cout << "Area: " << area << "\n";
11 std::cout << "Circumference: " << circumference << "\n";
12 return 0;
13}Radius: 10
Area: 314.159
Circumference: 62.8318Exercise 4: Integer division and the remainder operator do all the work:
1#include <iostream>
2
3int main() {
4 int totalSeconds = 0;
5 std::cout << "Seconds: ";
6 std::cin >> totalSeconds;
7 int hours = totalSeconds / 3600;
8 int minutes = totalSeconds % 3600 / 60;
9 int seconds = totalSeconds % 60;
10 std::cout << hours << " h " << minutes << " min " << seconds << " s\n";
11 return 0;
12}Seconds: 3725
1 h 2 min 5 sSeconds: 86399
23 h 59 min 59 sExercise 5: (1) int ticketPrice{12.50} is a narrowing error: a price with cents needs a double. (2) seats is const, so it can't be changed: keep the total as a constant and compute the seats left in a new variable. (3) With those fixed, it works:
1#include <iostream>
2
3int main() {
4 const int seats = 150;
5 double ticketPrice{12.50};
6 int tickets = 3;
7 int seatsLeft = seats - tickets;
8 std::cout << "Total: " << tickets * ticketPrice << "\n";
9 std::cout << "Seats left: " << seatsLeft << "\n";
10 return 0;
11}Total: 37.5
Seats left: 147Quiz: (1) The type (int), the name (age) and the initial value (35). (2) = stores a value in a variable; == asks whether two values are equal. (3) Both numbers are integers, so C++ does integer division and drops the remainder; make one a double to keep the decimals. (4) Brace initialization forbids narrowing conversions that lose information; = silently truncates 3.7 to 3. (5) It makes the variable read-only after it's initialized; any attempt to change it is a compile error.
Cheat sheet
| I want to… | Write |
|---|---|
| A whole number | int count = 0; |
| A really big whole number | long long population = 8000000000; |
| A number with decimals | double price = 4.99; |
| True or false | bool isReady = false; |
| One character | char initial = 'R'; |
| Text | std::string name = "Roger"; (with #include <string>) |
| Refuse lossy conversions | int score{42}; |
| Let the compiler pick the type | auto total = 0.0; |
| A value that never changes | const double pi = 3.14159; |
| Change a value | score = 10; / score += 5; / score++; |
| Divide keeping decimals | static_cast<double>(pizzas) / people |
| See a type's size | sizeof(int) |
Print true / false | std::cout << std::boolalpha << isReady; |
Wrapping up
Variables are how programs remember things:
- A variable has a type, a name and a value:
int age = 35;. - The type decides the size and the range: an
intis 4 bytes and stops at about 2.1 billion;longis 4 bytes on Windows but 8 on Linux and macOS. - Initialize every variable; reading one that has no value is a bug.
- Watch the number traps: integer division drops the remainder, values that don't fit wrap around without any warning, and decimals like 0.1 + 0.2 aren't exact.
- Braces
{ }catch narrowing,autodeduces the type, andconstlocks a value. - Pick descriptive names that follow the rules: letters, digits and underscores, never starting with a digit.
Next, use your variables to make decisions with the if statement, repeat work with the for loop, and store many values at once with C++ arrays.
Read next

What Is the Swift Programming Language? A Simple Guide to the Language Behind iPhone Apps
A friendly, jargon-free guide to Swift, the programming language Apple created for iPhone, iPad and Mac apps. Learn why it replaced Objective-C, how optionals prevent crashes, how an app is made, and how fast Swift really is.

What Is the Rust Programming Language? A Simple Guide to the Fast Language That Won't Let You Crash
A friendly, jargon-free guide to Rust, the programming language that is as fast as C but stops whole families of memory bugs before a program ever runs. Learn about ownership, why tech giants are adopting it, and where it is used.

What Is the Go Programming Language? A Simple Guide to the Language of the Cloud
A friendly, jargon-free guide to Go, the simple and fast programming language Google created for the cloud. Learn what goroutines are, why Go programs are a single file, and how Go came to power Docker, Kubernetes and much of the internet.
Comments
Be kind and specific. Comments with links from new accounts appear after a moderator reviews them.