Ch3: Variables and data types¶
TL;DR: Memory Representation: ข้อมูลทั้งหมดใน C++ จะเก็บเป็นเลขฐานสอง (Bit กลุ่มกันเป็น Byte) โดยเลขฐานแปด (Octal) และสิบหก (Hexadecimal) เป็นเพียงแค่รูปแบบแสดงผลเพื่อให้มนุษย์อ่านได้สะดวก
⚡ Quick Reference¶
#include <iostream>
#include <limits>
int main() {
// int x {5}; - ใช้ Brace initialization สำหรับกำหนดค่าเริ่มต้นแบบ Uniform
int a {5};
int b {}; // กำหนดค่าเริ่มต้นเป็น 0 (Zero-initialization)
// double, float, char, bool - ตัวแปรประเภทข้อมูลพื้นฐานต่างๆ
double d {3.14};
float f {2.5f};
char c {'A'};
bool ok {true};
// sizeof(type) - คำนวณหาขนาดของชนิดข้อมูลหรือตัวแปรในหน่วย Byte
std::cout << sizeof(int) << std::endl;
// signed, unsigned, short, long, long long - ตัวดัดแปลงขนาดและเครื่องหมายของจำนวนเต็ม
short int si {10};
long int li {100};
long long int lli {1000};
unsigned int ui {50u};
// const - ป้องกันไม่ให้แก้ไขค่าของตัวแปรหลังจากสร้างขึ้นมาแล้ว
const int limit = 100;
// auto - ให้คอมไพเลอร์คาดเดาประเภทข้อมูลจากค่าเริ่มต้นโดยอัตโนมัติ
auto value = 15.5;
// std::numeric_limits<T>::min() - ดึงค่าต่ำสุดและสูงสุดที่เป็นไปได้ของแต่ละประเภทข้อมูล
std::cout << std::numeric_limits<int>::min() << std::endl;
return 0;
}
🧠 Core Concepts¶
- Memory Representation: ข้อมูลทั้งหมดใน C++ จะเก็บเป็นเลขฐานสอง (Bit กลุ่มกันเป็น Byte) โดยเลขฐานแปด (Octal) และสิบหก (Hexadecimal) เป็นเพียงแค่รูปแบบแสดงผลเพื่อให้มนุษย์อ่านได้สะดวก
- Initialization Safety: การประกาศตัวแปรแบบใช้ปีกกา (
{}) จะป้องกันการแปลงข้อมูลที่ทำให้สูญเสียความละเอียด (Narrowing conversion) ตั้งแต่ตอน Compile ขณะที่แบบวงเล็บ (()) และแบบเครื่องหมายเท่ากับ (=) จะปัดเศษทิ้งอย่างเงียบๆ - Type Deduction: Keyword
autoช่วยให้ Compiler สามารถคาดเดาประเภทข้อมูลจากค่าเริ่มต้นได้ตอน Compile โดยใช้ Literal Suffix (เช่นf,u,ll) ในการระบุประเภทเฉพาะเจาะจง ซึ่งประเภทนี้จะถูกฟิกซ์ไว้และไม่สามารถเก็บข้อมูลประเภทอื่นในภายหลังได้
⚠️ Pitfalls (Quick Scan)¶
| ข้อผิดพลาด | วิธีแก้ |
|---|---|
| การประกาศตัวแปรโดยไม่ได้กำหนดค่าเริ่มต้น | ใช้ Braced Initialization เสมอ เช่น int elephant_count{}; |
| การเกิด Narrowing จากวิธี Functional หรือ Copy initialization | ใช้ Braced Initialization (int x{2.9};) เพื่อบังคับให้เกิด Compile error เมื่อข้อมูลลดรูป |
| ความสับสนในการใช้เลข 0 นำหน้าตัวเลขธรรมดา | ห้ามใส่เลข 0 นำหน้าเลขฐานสิบ และใช้ 0x หรือ 0b ในฐานอื่นแทน |
การลืมใส่ Suffix f สำหรับค่าประเภท float |
ใส่ Suffix f เสมอเมื่อระบุค่าทศนิยมให้กับตัวแปรประเภท float |
การกำหนดค่าติดลบให้กับตัวแปร unsigned ที่ถูกประกาศผ่าน auto |
เลี่ยงการใช้ auto ร่วมกับ Suffix u หากมีโอกาสที่ตัวแปรจะได้รับค่าติดลบในภายหลัง |
การเปลี่ยนค่าตัวแปรประเภท auto ด้วยรูปแบบข้อมูลที่ขัดแย้งกัน |
ระบุประเภทข้อมูลของตัวแปรตรงๆ หากค่านั้นจำเป็นต้องเก็บประเภทข้อมูลที่ต่างกันออกไป |
| การนำ 0.0 หารด้วย 0.0 | ตรวจสอบตัวหารก่อนทำประมวลผลทางคณิตศาสตร์เสมอ |
| การใช้ตัวเลขเกินข้อจำกัดความละเอียดของชนิดข้อมูลทศนิยม | เลือกชนิดข้อมูลทศนิยมให้เหมาะสมกับความละเอียดที่ต้องการใช้งาน และเลี่ยงการเปรียบเทียบทศนิยมตรงๆ |
📖 Full Details¶
Cause → Effect → Fix พร้อม timestamp (คลิกเพื่อดู)
* **การประกาศตัวแปรโดยไม่ได้กำหนดค่าเริ่มต้น** -> **การอ่านค่าขยะใน Memory มาใช้งานจะทำให้เกิด Undefined behavior** -> **ใช้ Braced Initialization เสมอ เช่น `int elephant_count{};` (8:50)** * **การเกิด Narrowing จากวิธี Functional หรือ Copy initialization** -> **ทศนิยมจะถูกตัดเศษทิ้งอย่างเงียบๆ (เช่น `2.9` เหลือ `2`) ทำให้ข้อมูลสูญหาย** -> **ใช้ Braced Initialization (`int x{2.9};`) เพื่อบังคับให้เกิด Compile error เมื่อข้อมูลลดรูป (9:50)** * **ความสับสนในการใช้เลข 0 นำหน้าตัวเลขธรรมดา** -> **Compiler จะมองว่าเป็นเลขฐานแปด (Octal) ทำให้ได้ค่าไม่ตรงกับที่คิด (เช่น `017` มีค่าเท่ากับ `15` ในฐานสิบ)** -> **ห้ามใส่เลข 0 นำหน้าเลขฐานสิบ และใช้ `0x` หรือ `0b` ในฐานอื่นแทน (6:11)** * **การลืมใส่ Suffix `f` สำหรับค่าประเภท `float`** -> **ตัวเลขจะถูกมองเป็น `double` ก่อนจะตัดรูปมาเป็น `float` ทำให้เสี่ยงสูญเสียความละเอียด** -> **ใส่ Suffix `f` เสมอเมื่อระบุค่าทศนิยมให้กับตัวแปรประเภท `float` (24:38)** * **การกำหนดค่าติดลบให้กับตัวแปร `unsigned` ที่ถูกประกาศผ่าน `auto`** -> **Compiler ยอมทำงานและปัดค่ากลับมาเป็นบวกที่มีค่ามหาศาลแทน** -> **เลี่ยงการใช้ `auto` ร่วมกับ Suffix `u` หากมีโอกาสที่ตัวแปรจะได้รับค่าติดลบในภายหลัง (41:16)** * **การเปลี่ยนค่าตัวแปรประเภท `auto` ด้วยรูปแบบข้อมูลที่ขัดแย้งกัน** -> **Compiler จะบังคับแปลงค่าเหล่านั้นให้อยู่ในประเภทแรกที่คาดเดาไว้ ทำให้เกิดข้อมูลเพี้ยน** -> **ระบุประเภทข้อมูลของตัวแปรตรงๆ หากค่านั้นจำเป็นต้องเก็บประเภทข้อมูลที่ต่างกันออกไป (41:16)** * **การนำ 0.0 หารด้วย 0.0** -> **ได้ผลลัพธ์เป็น `NaN` (Not a Number) ซึ่งจะแพร่กระจายไปทำลายการคำนวณถัดๆ ไปทั้งหมด** -> **ตรวจสอบตัวหารก่อนทำประมวลผลทางคณิตศาสตร์เสมอ (24:22)** * **การใช้ตัวเลขเกินข้อจำกัดความละเอียดของชนิดข้อมูลทศนิยม** -> **ข้อมูลส่วนเกินขีดจำกัด (`~7` หลักสำหรับ `float`, `~15` หลักสำหรับ `double`) จะกลายเป็นค่าขยะ** -> **เลือกชนิดข้อมูลทศนิยมให้เหมาะสมกับความละเอียดที่ต้องการใช้งาน และเลี่ยงการเปรียบเทียบทศนิยมตรงๆ (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