Lecture 2
Types in C++
Types
In Python, types are inferred from the value or are hinted.
For example, this was how we could initialize variable with and without types.
Modern C++ actually works in a similar manner! Except we don't consider typing a variable a hint. Providing the type is actually the default behavior
Note that the auto keyword allows us to infer the type from the right-hand value. These days, it's
considered a best practice to use the auto keyword especially if you're initializing the variable.
Declaration vs initialization
Something that wasn't prevalent in Python is the idea of declarations. In C++, you're allowed to declare a variable without assigning it a value.
Declarations are a way to reserve space for a variable without needing it to have a value right away.
The different ways we learn how to reserve or request space for data in C++ is part of the memory control that we're exposed to with the language. The distinction will become a lot more obvious in the future once we demystify the distinction between stack and heap allocations
Data types in C++
Numbers
When we were in Python, we had two types for numbers: int and float. Complexities around overflows and size of the number
were abstracted away into something that just works.
C++ uncovers this layer of abstraction for us by forcing us to choose the type for our number.
int
You would declare your variable to be an int if you wanted to store whole numbers. However, like I mentioned before, our choice of type is driven by how large of a number we expect to store in this variable.
When you choose to use an int, you are guaranteed that the int is at least 16 bits wide.
Different hardware and compilers can choose a larger size as long as it meets the minimum. You'll see that in practice,
| Platform | sizeof(int) |
|---|---|
| x86-64, ARM64 | 4 bytes (32 bits) |
| Old 16-bit embedded systems | 2 bytes (16 bits) |
| Some historical systems | 8 bytes (64 bits) |
In most cases, this means that int will have a size of 32 bits. So the range of values that fit within an int fall between
We also have something called an unsigned int which has the same size as int, but does not allow for negative numbers.
This means that the range of values it falls within actually doubles on the positive side. Therefore, the range of values
for an unsigned int within a 32-bit system is
long long / long long int
You would use long long if you wanted to store whole numbers that are at least 64 bits wide.
Because we know that it's at least 64 bits wide, then the range of values should fall from
There is also a long type, but because of its cross-platform behavior, it's recommended to use long long if we want
to guarantee at least 64 bits.
- By cross-platform behavior, I meant to say that Windows will have a different size for
longdepending on whether you're using a 32-bit or 64-bit system. MacOS and Linux both treatlongas something that's at least 64 bits wide.
float / double
If you need real numbers, then float and double are the types you'll need.
The difference between the two types is the amount of precision you have with the decimal places.
floathas about ~6-7 significant decimal digitsdoublehas about ~15-16 significant decimal digits
In most cases, you'll want to use double unless memory or performance is a hard constraint.
Booleans
For booleans, there are two types of values: true and false.
Note that these are spelled with lowercase t and f unlike the Python equivalents.
bool
The sizeof(bool) is guaranteed to be at least 1 byte. It can't be smaller than a byte because a byte is the smallest
addressable unit as you can't take the address of a single bit
Not always. Depending on where you initialize it, the value could be indeterminate! That being said, it's a best practice to always initialize explicitly
Characters
char
A char stores a single character and is always exactly 1 byte (8 bits).
Under the hood, a char is just a small integer — each character is mapped to a number
via the ASCII encoding standard. For example, 'A' is 65 and 'a' is 97.
Note that character literals use single quotes ('), not double quotes.
Because char is really an integer, you can do arithmetic with it:
Like int, char can also be unsigned. A plain char may be signed or unsigned depending
on the platform, so if you care about the sign, prefer signed char or unsigned char explicitly.
| Type | Range (typical) |
|---|---|
char (signed) | −128 to 127 |
unsigned char | 0 to 255 |
std::string
For text longer than a single character, C++ provides std::string in the <string> header.
Some operations you'll use frequently:
C also has a string type: a null-terminated char array like char name[] = "morty". You'll
still see these in older code and when interfacing with C libraries, but for new C++ code always
prefer std::string. It manages its own memory and is much safer to work with.
Type Casting
Sometimes you need to convert a value from one type to another. This is called type casting.
Implicit casting
C++ will automatically convert between compatible types in certain situations. This is called an implicit cast (or coercion).
When going from a larger or more precise type to a smaller one (e.g. double → int), you lose information.
This is called a narrowing conversion and is a common source of bugs.
Explicit casting with static_cast
The preferred C++ way to cast explicitly is static_cast<TargetType>(value). It makes your intent clear and
lets the compiler catch mistakes:
The second example is a very common pattern. Without the cast, 7 / 2 is integer division and gives 3.
Casting one operand to double forces floating-point division.
You may see C-style casts like (int)pi in older code. They work but bypass some of the
compiler's safety checks. Prefer static_cast in new C++ code.
I/O operations
C++ handles input and output through the <iostream> header.
Output with std::cout
std::cout (character output) writes to the terminal. The << operator chains values together:
You may also see std::endl used to end a line. It works, but it flushes the output buffer every time
which is slower. Prefer "\n" unless you specifically need a flush.
Input with std::cin
std::cin (character input) reads from the terminal. The >> operator extracts into a variable:
std::cin >> skips leading whitespace and stops at the next whitespace, which means it reads one
word at a time. To read an entire line including spaces, use std::getline:
If you use std::cin >> before std::getline, the leftover newline in the buffer will cause
getline to immediately return an empty string. Fix this by calling std::cin.ignore() between them.
Operators in C++
Arithmetic operators
These are the standard math operations. They work on numeric types (int, double, etc.):
| Operator | Meaning | Example | Result |
|---|---|---|---|
+ | Addition | 3 + 2 | 5 |
- | Subtraction | 3 - 2 | 1 |
* | Multiplication | 3 * 2 | 6 |
/ | Division | 7 / 2 | 3 (integer!) |
% | Modulo (remainder) | 7 % 2 | 1 |
The most important thing to keep in mind is that / on two integers performs integer division — it discards
the remainder. Use static_cast<double> on one operand if you need a decimal result.
% (modulo) only works on integers and returns the remainder after division. It's useful for things like
checking if a number is even (n % 2 == 0).
Increment and decrement operators
These are shorthand for adding or subtracting 1 from a variable:
The difference between pre (++i) and post (i++) matters when the expression is used as a value:
- Post-increment (
i++) returns the old value, then increments. - Pre-increment (
++i) increments first, then returns the new value.
In a standalone statement (not embedded in a larger expression), both behave identically.
Comparison operators
Comparison operators evaluate to a bool (true or false):
| Operator | Meaning | Example | Result |
|---|---|---|---|
== | Equal to | 3 == 3 | true |
!= | Not equal to | 3 != 4 | true |
< | Less than | 3 < 4 | true |
> | Greater than | 3 > 4 | false |
<= | Less than or equal | 3 <= 3 | true |
>= | Greater than or equal | 4 >= 5 | false |
A very common mistake is using = (assignment) instead of == (comparison) inside an if
condition. if (x = 5) assigns 5 to x and is always truthy — it does not check if x equals 5.
Assignment operators
Beyond the basic =, C++ provides compound assignment operators that combine an arithmetic operation with assignment:
| Operator | Equivalent to | Example | Result (if x = 10) |
|---|---|---|---|
= | — | x = 5 | x is 5 |
+= | x = x + n | x += 3 | x is 13 |
-= | x = x - n | x -= 3 | x is 7 |
*= | x = x * n | x *= 2 | x is 20 |
/= | x = x / n | x /= 2 | x is 5 |
%= | x = x % n | x %= 3 | x is 1 |
Logical operators
Logical operators combine or negate boolean expressions:
| Operator | Meaning | Example | Result |
|---|---|---|---|
&& | Logical AND | true && false | false |
|| | Logical OR | true || false | true |
! | Logical NOT | !true | false |
&& and || use short-circuit evaluation: if the result is determined by the left operand alone,
the right operand is never evaluated.
Exercises
Q1.
For each value below, choose the most appropriate C++ type (int, unsigned int, long long, float, double, bool, char, std::string) and briefly explain why:
- The number of students enrolled in a course (never negative, fits in tens of thousands).
- A student's GPA (e.g.
3.75). - Whether a student has passed the course.
- A single letter grade (
'A','B', …). - A student's full name.
- The total number of grains of sand on Earth (~).
Q2.
Without running the code, determine what each std::cout statement prints. Then verify by compiling and running.
Q3.
Write a complete C++ program that does the following:
- Prompts the user to enter their first name and last name on a single line (use
std::getline). - Prompts the user to enter their age as an integer.
- Prompts the user to enter their GPA as a
double. - Prints a formatted summary, for example:
Make sure to #include the necessary headers and handle the cin >> age / getline mixing issue.
Q4.
Each snippet below contains a subtle bug or unexpected behavior related to types and casting. Identify what goes wrong in each case, explain why, and write a corrected version.
Practice Problems
- FizzBuzz — Easy
- Add Digits — Easy
- Reverse Integer — Medium