2. Variables & Data Types¶
What & why¶
A variable is a named piece of memory that holds a value. Unlike Python or JavaScript, C++ is statically typed: every variable has a type fixed at compile time, and the compiler uses it to catch mistakes and to decide how much memory to reserve and which machine instructions to use.
Declaring variables¶
int count = 0; // whole number
double price = 9.99; // floating-point number
char grade = 'A'; // single character (single quotes!)
bool is_ready = true; // true or false
std::string name = "Ada"; // text (needs #include <string>)
The pattern is type name = initial_value;.
The fundamental types¶
| Type | Holds | Typical size | Example |
|---|---|---|---|
int |
whole numbers | 4 bytes (≈ ±2.1 billion) | 42 |
long long |
bigger whole numbers | 8 bytes | 9'000'000'000LL |
unsigned int |
non-negative whole numbers | 4 bytes | 42u |
double |
real numbers, ~15 digits precision | 8 bytes | 3.14159 |
float |
real numbers, ~7 digits precision | 4 bytes | 3.14f |
char |
one byte / character | 1 byte | 'x' |
bool |
truth value | 1 byte | true |
std::string is not built in — it's a class from the standard library — but you'll use it like one.
Check sizes on your machine:
#include <iostream>
int main() {
std::cout << "int: " << sizeof(int) << " bytes\n";
std::cout << "double: " << sizeof(double) << " bytes\n";
std::cout << "char: " << sizeof(char) << " bytes\n";
}
Need an exact width?
#include <cstdint>gives youstd::int32_t,std::uint8_t,std::int64_t, etc.
Initialization: always give a value¶
int a; // UNINITIALIZED: holds garbage. Reading it is undefined behavior.
int b = 5; // copy initialization
int c{5}; // brace (uniform) initialization — preferred in modern C++
int d{}; // value-initialized to 0
Brace initialization refuses narrowing conversions, which catches bugs:
int x = 3.9; // compiles, silently becomes 3 (warning with -Wall, maybe)
int y{3.9}; // compile ERROR: narrowing conversion from double to int
Rule of thumb: initialize every variable when you declare it, and prefer {}.
auto: let the compiler deduce the type¶
auto n = 10; // int
auto pi = 3.14; // double
auto letter = 'q'; // char
auto s = std::string{"hi"}; // std::string
auto t = "hi"; // const char* — NOT std::string! (a C-style string)
auto is great for long type names; don't use it when the type is important to a reader.
const and constexpr¶
const double tax_rate = 0.08; // can't be changed after initialization
constexpr int days_per_week = 7; // must be known at compile time
tax_rate = 0.1; // compile ERROR: assignment of read-only variable
Make things const by default. It documents intent and lets the compiler stop accidental changes.
Type conversion¶
Some conversions happen automatically (implicit):
Others you ask for (explicit) with static_cast:
Converting strings ↔ numbers:
#include <string>
int n = std::stoi("42"); // string → int
double x = std::stod("3.5"); // string → double
std::string s = std::to_string(99); // number → string
std::stoi("abc") throws an exception — we'll handle those in lesson 11.
Scope¶
A variable exists from its declaration to the closing } of the block that contains it:
int main() {
int outer = 1;
{
int inner = 2;
std::cout << outer + inner << '\n'; // fine
}
std::cout << inner << '\n'; // ERROR: 'inner' was not declared in this scope
}
Declare variables as close as possible to where they're first used.
Naming¶
- Letters, digits, and
_; can't start with a digit; case-sensitive. - Can't be a keyword (
int,class,return, ...). - Pick a style and be consistent:
snake_case(the standard library) orcamelCase. - Avoid names starting with
_followed by a capital, or containing__— they're reserved.
Common mistakes¶
- Using an uninitialized variable — the program may "work" today and print garbage tomorrow.
char c = "A";— double quotes make a string; characters use single quotes'A'.auto s = "hi";expecting astd::string— it's aconst char*.- Integer overflow —
int big = 3'000'000'000;doesn't fit in anint. - Shadowing — declaring a new variable with the same name in an inner scope hides the outer one.
-Wshadowwarns about it.
Exercises¶
- Declare one variable of each fundamental type, print them all, and print
sizeofeach. - Write a program that reads a temperature in Celsius as a
doubleand prints Fahrenheit (F = C * 9 / 5 + 32). - Try
int x{3.9};. Read the error. Fix it withstatic_cast. - Read a number as a
std::stringwithstd::cin, convert it withstd::stoi, double it, and print it. - Remove the initializer from an
intand print it. Compile with-Wall -Wextra. What does the compiler say? What does the program print?
Recap¶
- Every variable has a fixed type:
int,double,char,bool,std::string, ... - Always initialize; prefer brace initialization
int x{5};because it blocks narrowing. autodeduces the type from the initializer.const/constexprmake values read-only — use them by default.static_cast<T>(x)for explicit conversions;std::stoi/std::to_stringfor text.- Variables live until the end of their enclosing
{ }block.
Next: Numbers & math →