class: center, middle # CMPE 30: Lecture 2 Variables --- # What does std::cin >> name store for "Los Del Rio"? .lc[ ```cpp #include
#include
int main() { std::string name; std::cin >> name; std::cout << name << "\n"; } ``` ] .rc[ 1. `Los Del Rio` 1. `Los` 1. `Rio` 1. an empty string 1. Ben got this wrong ] --- # Learning Objectives - Name the fundamental types (including `long double`) and their sizes - Use `
` fixed-width types when the exact size matters - Declare, initialize, and never leave variables uninitialized - Know the initialization forms --- braces reject narrowing - Use `sizeof` and `std::numeric_limits
` - Declare and index 1D and 2D arrays safely - Use `const` for read-only values (and pointers) - Group fields with a `struct` and access them with `.` --- # Why Variables? - Without variables, you can only use **literal** values - A variable gives a **name** to a piece of typed memory - Every variable has a **type** set at compile time - In C++, "object" = any region of memory with a type (not just OOP!) --- # Basic Types .lc[ ```cpp int score = 99; short small = 42; long big = 1'000'000L; long long huge = 9'000'000'000LL; unsigned int positive = 42; float price = 9.99f; double pi = 3.14159265358979; long double e = 2.718281828459045235L; char grade = 'A'; bool game_over = false; ``` ] .rc[ - Integers differ in **size** and **range** - Prefer `double` over `float` - `long double` = extra precision, platform-dependent size - A `char` is a tiny integer: `'A'` is 65 - **Single** quotes for chars, **double** for strings ] --- # char Is a Number: ASCII .lc[ ```cpp char letter = 65; int number = 65; std::cout << letter << "\n"; // A std::cout << number << "\n"; // 65 char c = 'A'; c = c + 1; // 'B' ``` ] .rc[ - **ASCII** maps 0-127 to characters - `'A'` is 65, `'a'` is 97, `'0'` is 48 - `std::cout` picks the display by **type**: `char` = glyph, `int` = digits - Adding 1 gives the next code point ] --- # Fixed-Width Integer Types .lc[ ```cpp #include
std::int32_t fans = 1'000'000; std::uint8_t red = 255; std::uint16_t port = 8080; ``` ] .rc[ - `int`/`long` sizes are only **minimums** - `
` types are **exactly** the named width - Use when size matters: file formats, packets, hardware - Plain `int` is still the everyday default ] --- # Declaring and Initializing .lc[ ```cpp int waterfalls = 3; int x = 0, y = 0, z = 0; int count; // uninitialized --- garbage! auto w = 3; // int auto s = 88.0; // double auto c = 'T'; // char ``` ] .rc[ - Declare multiple of the same type in one line - **Always** initialize --- uninitialized variables hold whatever garbage was there before - `auto` asks the compiler to deduce the type - C++ is still strictly typed with `auto` ] --- # Initialization Forms .lc[ ```cpp int a = 10; // copy init int b(10); // direct init int c{10}; // brace init int oops = 99.9; // compiles: 99 int safer{99.9}; // ERROR ``` ] .rc[ - All three store 10 - Braces (C++11) **reject narrowing** conversions - `= 99.9` into an `int` silently drops the `.9` - Prefer braces to catch suspicious conversions ] --- # sizeof and std::numeric_limits .lc[ ```cpp #include
#include
int main() { std::cout << sizeof(int) << "\n"; std::cout << std::numeric_limits
::max() << "\n"; } ``` ] .rc[ - `sizeof(type)` --- parens required for a type - `sizeof(char)` is **always 1** - `std::numeric_limits
` lives in `
` - `min()`, `max()`, `lowest()` query the range - For floats, `min()` is the smallest **positive** normal --- use `lowest()` for most negative ] --- # Arrays .lc[ ```cpp int scores[5] = {99, 85, 73, 91, 100}; std::cout << scores[0] << "\n"; // 99 std::cout << scores[4] << "\n"; // 100 int primes[] = {2, 3, 5, 7, 11}; int n = sizeof(primes) / sizeof(primes[0]); ``` ] .rc[ - Fixed size, contiguous memory - Indices **0** to **size - 1** - Let the compiler count with `[]` - **No bounds checking** --- `scores[5]` is undefined behavior - `sizeof/sizeof` trick for element count ] --- # 2D Arrays .lc[ ```cpp int grid[3][4] = { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12} }; std::cout << grid[0][0]; // 1 std::cout << grid[2][3]; // 12 ``` ] .rc[ - "3 rows of 4 ints each" - First index = row, second = column - Elements laid out **row by row** in memory - Neighbors: `grid[0][3]` and `grid[1][0]` ] --- # const .lc[ ```cpp const double PI = 3.14159265358979; const int MAX_LIVES = 3; int vida = 99; const int *p1 = &vida; // const int int *const p2 = &vida; // const ptr const int *const p3 = &vida; ``` ] .rc[ - `const` = read-only, enforced by the compiler - `const int *p1` --- cannot change the value through `p1`, but can repoint - `int *const p2` --- cannot repoint, but can change the value - Read **right to left** ] --- # Structures .lc[ ```cpp struct Song { std::string title; std::string artist; int year; }; Song favorite; favorite.title = "Waterfalls"; favorite.artist = "TLC"; favorite.year = 1995; Song hit = {"No Scrubs", "TLC", 1999}; ``` ] .rc[ - Groups related fields under one type - Access members with the **dot** operator - Brace initialization is shorter - **Assignment copies every member** --- each struct has its own storage ] --- # Designated Initializers .lc[ ```cpp struct Song { std::string title; std::string artist; int year; }; Song hit = {.title = "No Scrubs", .artist = "TLC", .year = 1999}; Song stub = {.title = "Wonderwall"}; // artist = "", year = 0 ``` ] .rc[ - Name each member (C++20) - Harder to mis-order, self-documenting - Members must stay in **declaration order** --- skip, never reorder - Skipped members get defaults: `0`, empty string ] --- # Try It: Playlist .lc[ ```cpp struct Cancion { std::string titulo; std::string artista; int anio; }; Cancion playlist[3] = { {"Waterfalls", "TLC", 1995}, {"No Scrubs", "TLC", 1999}, {"Livin' La Vida Loca", "Ricky Martin", 1999} }; ``` ] .rc[ - Predict the output of the print loop - What is `sizeof(playlist) / sizeof(playlist[0])`? - Add a fourth song --- does the count keep up? - Rewrite one entry with designated initializers ] --- # What is printed? .lc[ ```cpp #include
int main() { char c = 'C'; c = c + 3; std::cout << c << "\n"; } ``` ] .rc[ 1. `C3` 1. `C` 1. `F` 1. `70` 1. Ben got this wrong ] --- # What is sizeof(scores) for int scores[10]? On a system where `int` is 4 bytes: 1. 4 1. 10 1. 14 1. 40 1. Ben got this wrong --- # Which lets you change *p but not where p points? 1. `const int *p` 1. `int const *p` 1. `int *const p` 1. `const int *const p` 1. Ben got this wrong --- # Key Points - Every variable has a type; the type sets size and legal operations - **Always initialize** --- no uninitialized variables - `sizeof` is in bytes; `std::numeric_limits
` for ranges - Arrays are fixed-size, zero-indexed, **no bounds checking** - Read pointer `const` **right to left** - `struct` assignment copies every member **Read:** chapter 3 of *Gorgo Starting C++*. **Do:** exercises 1-15.