Variables, types, and constants
Starting out12 min readLesson 3 of 6
3.1 Values need names and types
A variable is a named region of memory that holds a value. Its type tells the compiler how much space to reserve and which operations make sense. int stores whole numbers, double stores numbers with a fractional part, char stores one character, and bool stores true or false. Text uses std::string, which comes from <string>.
Declare a variable before you use it. Initializing on the same line avoids an unpredictable starting value and makes the purpose clear.
#include <iostream>
#include <string>
int main() {
int age = 15;
double height = 1.63;
char grade = 'A';
bool passed = true;
std::string name = "Ravi";
std::cout << name << " is " << age << " years old.\n";
std::cout << "Height: " << height << " m\n";
std::cout << "Grade: " << grade << "\n";
std::cout << "Passed: " << passed << "\n";
return 0;
}Output
Ravi is 15 years old. Height: 1.63 m Grade: A Passed: 1
3.1.1 Declaration and initialization
These forms are common:
int count;declares the variable and leaves it uninitialized. Reading a local variable before assignment is undefined behavior.int count = 0;copies the value into the variable.int count{0};uses brace initialization, which rejects some narrowing conversions.int count = {0};combines both forms.
Brace initialization is the safer default in new code. For example, int size{2.9}; fails to compile. An assignment without braces can silently drop the fractional part.
#include <iostream>
int main() {
int score{42};
double average{88.5};
const int passes_needed{40};
auto bonus = score + 8;
std::cout << "Score: " << score << "\n";
std::cout << "Average: " << average << "\n";
std::cout << "Passes needed: " << passes_needed << "\n";
std::cout << "Bonus score: " << bonus << "\n";
return 0;
}Output
Score: 42 Average: 88.5 Passes needed: 40 Bonus score: 50
3.1.2 Constants and inferred types
Add const when a name should never change after initialization. const int max_players = 11; makes a later assignment a compile error and documents the intent.
The auto keyword asks the compiler to infer the type from the initializer. auto is useful for long standard library types, and it can hide the type from a reader. Use it when the initializer makes the type obvious, as in auto pages = 320;.
3.1.3 Working with text
std::string owns a sequence of characters. You can initialize it with a literal, join strings with +, append with +=, and ask for its size with .size(). Indexing starts at zero, so word[0] is the first character.
A string literal such as "hello" and a std::string object are different types. The compiler converts a literal when it initializes a string object, and #include <string> is required.
#include <iostream>
#include <string>
int main() {
std::string first = "Ada";
std::string last = "Lovelace";
std::string full = first + " " + last;
std::cout << full << "\n";
std::cout << "Letters: " << full.size() << "\n";
std::cout << "First initial: " << full[0] << "\n";
return 0;
}Output
Ada Lovelace Letters: 12 First initial: A
3.1.4 Mixing whole numbers and decimals
When both operands are integers, / performs integer division. 7 / 2 produces 3, and % gives the remainder 1. If one operand is a double, the division keeps the fractional part.
A cast converts a value on purpose. static_cast<double>(total) produces a double before the division happens. Use a cast when you mean to change the type, and keep the cast close to the operation it affects.
#include <iostream>
int main() {
int total = 17;
int people = 5;
std::cout << "Integer division: " << total / people << "\n";
std::cout << "Remainder: " << total % people << "\n";
double exact = static_cast<double>(total) / people;
std::cout << "Exact: " << exact << "\n";
return 0;
}Output
Integer division: 3 Remainder: 2 Exact: 3.4
3.1.5 Characters and truth values
A char holds one character in single quotes, as in 'A'. A bool holds true or false. By default, std::cout prints a bool as 1 or 0. The std::boolalpha manipulator switches later output on that stream to true and false.
Single quotes and double quotes are different. 'A' is a character, and "A" is a string literal.
#include <iostream>
int main() {
char grade = 'A';
bool passed = true;
std::cout << std::boolalpha;
std::cout << "Grade: " << grade << "\n";
std::cout << "Passed: " << passed << "\n";
return 0;
}Output
Grade: A Passed: true
3.1.6 Scope and shadowing
A variable lives inside the block where it is declared. An inner block can redeclare the same name, which creates a new variable and hides the outer one. This is shadowing. It compiles, and it makes the code harder to follow. Choose a distinct name when an inner block needs a related value.
Global variables are visible across the file and make data flow hard to trace. Beginner programs can keep almost everything inside main, then move pieces into functions when the logic grows.
#include <iostream>
int main() {
int count = 3;
{
int count = 10;
std::cout << "Inner: " << count << "\n";
}
std::cout << "Outer: " << count << "\n";
return 0;
}Output
Inner: 10 Outer: 3
3.1.7 Practice
- Create variables for a name, age, height, and pass status, then print one line for each.
- Declare a
const doublefor a tax rate and try to assign to it. Read the compiler error. - Compute the average of three integer marks with
static_cast<double>so the result keeps its decimal part. - Use braces to initialize an
intwith4.8and confirm that the compiler refuses the narrowing conversion.
