Variables and Types
A variable is a named, typed piece of memory. C++ is statically typed — every variable has a type fixed at compile time — but modern C++ lets the compiler work out many types for you with auto, and brace initialisation catches mistakes that older styles let through.
Declaring variables
#include <iostream> #include <string> int main() { int age = 36; double height = 1.74; char initial = 'S'; bool member = true; std::string name = "Sam"; std::cout << name << " (" << initial << "), " << age << " years, " << height << " m, member: " << member << '\n'; age = age + 1; std::cout << "Next year: " << age << '\n'; }
Sam (S), 36 years, 1.74 m, member: 1 Next year: 37
bool prints as 1 or 0 by default; lesson 7 shows how to print true/false.
Fundamental types
| Type | Holds | Typical size |
|---|---|---|
bool | true / false | 1 byte |
char | A single character (a small integer) | 1 byte |
int | Whole numbers, about ±2.1 billion | 4 bytes |
long long | Larger whole numbers, about ±9.2 × 1018 | 8 bytes |
unsigned versions | Non-negative only, twice the range | same |
float / double | Floating point, ~7 / ~15 digits | 4 / 8 bytes |
std::size_t | Sizes and indexes (unsigned) | 8 bytes on 64-bit |
Sizes are only guaranteed minimums; sizeof tells you the real size. For exact sizes use <cstdint>'s std::int32_t, std::uint8_t and friends. std::string isn't built in — it's a class from the standard library (lesson 8).
#include <iostream> #include <cstdint> int main() { std::cout << "int: " << sizeof(int) << ", long long: " << sizeof(long long) << ", double: " << sizeof(double) << ", int64_t: " << sizeof(std::int64_t) << '\n'; }
int: 4, long long: 8, double: 8, int64_t: 8
Brace initialisation
C++ has several ways to initialise a variable. Braces ({}), called uniform or list initialisation, work everywhere and refuse narrowing conversions that lose data:
int main() { int a = 3.9; // compiles: silently becomes 3 int b{3.9}; // error: narrowing from double to int return a + b; }
main.cpp:3:11: error: type 'double' cannot be narrowed to 'int' in initializer list [-Wc++11-narrowing]
#include <iostream> int main() { int count{}; // value-initialised: 0 double ratio{0.75}; int total{10}; std::cout << count << ' ' << ratio << ' ' << total << '\n'; }
0 0.75 10
Empty braces give zero (or the type's default). A local variable with no initialiser at all holds garbage — always initialise.
auto
auto tells the compiler to deduce the type from the initialiser. It saves typing long type names and keeps code correct when types change:
#include <iostream> #include <string> #include <vector> int main() { auto count = 42; // int auto price = 9.99; // double auto letter = 'x'; // char auto title = std::string{"C++"}; // std::string auto big = 3'000'000'000LL; // long long (' separates digits) std::vector<int> v{1, 2, 3}; auto size = v.size(); // std::size_t std::cout << count << ' ' << price << ' ' << letter << ' ' << title << ' ' << big << ' ' << size << '\n'; }
42 9.99 x C++ 3000000000 3
Watch out: auto name = "Sam"; deduces const char* (a C string), not std::string. Use auto where the type is obvious or unimportant; spell it out where it helps the reader.
Integer division and overflow
#include <iostream> #include <limits> int main() { std::cout << 7 / 2 << ' ' << 7.0 / 2 << ' ' << 7 % 2 << '\n'; std::cout << "int max: " << std::numeric_limits<int>::max() << '\n'; }
3 3.5 1 int max: 2147483647
Dividing two integers discards the fraction. Overflowing a signed integer is undefined behaviour (lesson 51) — choose long long when values can be large.
Try it yourself
Store a product's name, price and stock with appropriate types (use auto for at least one) and print the stock value.
Notebook: 40 x 3.5 = 140