Ch3: Variables and data types¶
TL;DR: Memory Representation: All data in C++ is stored as binary digits (bits grouped into bytes); binary, octal, and hexadecimal are human-readable representations of memory states.
โก Quick Reference¶
#include <iostream>
#include <limits>
int main() {
// int x {5}; - Brace initialization representing uniform initialization syntax.
int a {5};
int b {}; // Zero-initialized integer.
// double, float, char, bool - Fundamental types of variables.
double d {3.14};
float f {2.5f};
char c {'A'};
bool ok {true};
// sizeof(type) - Computes size of types or variables.
std::cout << sizeof(int) << std::endl;
// signed, unsigned, short, long, long long - Integer size and signedness modifiers.
short int si {10};
long int li {100};
long long int lli {1000};
unsigned int ui {50u};
// const - Prevents variable value mutations.
const int limit = 100;
// auto - Deduces variable types automatically from initializers.
auto value = 15.5;
// std::numeric_limits<T>::min() - Retrieves minimum and maximum value ranges.
std::cout << std::numeric_limits<int>::min() << std::endl;
return 0;
}
๐ง Core Concepts¶
- Memory Representation: All data in C++ is stored as binary digits (bits grouped into bytes); binary, octal, and hexadecimal are human-readable representations of memory states.
- Initialization Safety: Braced initialization (
{}) prevents narrowing conversions at compile time, whereas functional (()) and copy (=) initialization silently truncate data. - Type Deduction: The
autokeyword deduces variable types at compile time from initializers, which are fixed at declaration and can be specified using literal suffixes (e.g.,f,u,ll).
โ ๏ธ Pitfalls (Quick Scan)¶
| Mistake | Fix |
|---|---|
| Declaring uninitialized variables | Always use braced initialization, e.g., int elephant_count{}; |
| Using functional or assignment initialization with narrowing values | Use braced initialization (int x{2.9};) to trigger compile-time errors for narrowing |
Preceding integer literals with a leading zero (0) |
Avoid leading zeros for decimal literals, and use hex (0x) or binary (0b) for other bases |
Omitting the f suffix on float literals |
Always append the f suffix when initializing float variables |
Reassigning negative values to unsigned variables declared via auto |
Avoid using auto with unsigned suffixes if the variable might receive negative values later |
Reassigning incompatible values to auto-deduced variables |
Use explicit type declarations when variables must hold values of differing types over time |
| Dividing floating-point zero by zero | Validate denominators and check for NaN before processing mathematical operations |
| Exceeding floating-point precision limits | Choose appropriate floating-point types based on precision requirements, and avoid comparing floats directly |
๐ Full Details¶
Cause โ Effect โ Fix with timestamp (click to expand)
* **Declaring uninitialized variables** -> **Retrieving indeterminate garbage values from memory causes undefined behavior** -> **Always use braced initialization, e.g., `int elephant_count{};` (8:50)** * **Using functional or assignment initialization with narrowing values** -> **Floating-point values are silently truncated (e.g., `2.9` becomes `2`), leading to data loss** -> **Use braced initialization (`int x{2.9};`) to trigger compile-time errors for narrowing (9:50)** * **Preceding integer literals with a leading zero (`0`)** -> **Compiler interprets the literal as octal, leading to unexpected values (e.g., `017` becomes `15`)** -> **Avoid leading zeros for decimal literals, and use hex (`0x`) or binary (`0b`) for other bases (6:11)** * **Omitting the `f` suffix on `float` literals** -> **Literal defaults to `double` and silently truncates to `float` during initialization, risking precision loss** -> **Always append the `f` suffix when initializing `float` variables (24:38)** * **Reassigning negative values to unsigned variables declared via `auto`** -> **Compiler silently accepts the assignment and wraps the value, producing a massive positive integer** -> **Avoid using `auto` with unsigned suffixes if the variable might receive negative values later (41:16)** * **Reassigning incompatible values to `auto`-deduced variables** -> **Compiler forces conversion to the fixed deduced type, generating corrupt or wrapped values** -> **Use explicit type declarations when variables must hold values of differing types over time (41:16)** * **Dividing floating-point zero by zero** -> **Produces `NaN` (Not a Number), which silently propagates through and invalidates arithmetic calculations** -> **Validate denominators and check for `NaN` before processing mathematical operations (24:22)** * **Exceeding floating-point precision limits** -> **Data exceeding limits (`~7` digits for `float`, `~15` for `double`) is replaced with garbage digits** -> **Choose appropriate floating-point types based on precision requirements, and avoid comparing floats directly (25:58, 26:15)**๐ Repo Files¶
04.VariablesAndDatatypes/4.2NumberSystems/main.cpp04.VariablesAndDatatypes/4.3IntegerTypes/main.cpp04.VariablesAndDatatypes/4.4IntegerModifiers/main.cpp04.VariablesAndDatatypes/4.5FractionalNumbers/main.cpp04.VariablesAndDatatypes/4.6Booleans/main.cpp04.VariablesAndDatatypes/4.7CharactersAndText/main.cpp04.VariablesAndDatatypes/4.8Auto/main.cpp04.VariablesAndDatatypes/4.9Assignments/main.cpp