S SmartDocs
Série: C++ cpp 237 lignes · Mis à jour 2026-04-03

data_types.cpp

C++/Part1_基礎入門/Ch02_變數與資料型別/data_types.cpp

// ============================================================
// Ch02 - 資料型別、sizeof、型別範圍與轉換
// 編譯:g++ -std=c++17 -Wall -o data_types data_types.cpp
// 執行:./data_types
// ============================================================

#include <iostream>
#include <limits>      // std::numeric_limits
#include <cstdint>     // 固定寬度整數型別

int main() {
    // ══════════════════════════════════════════
    // 1. sizeof — 查看各型別佔用的記憶體大小
    // ══════════════════════════════════════════
    std::cout << "=== sizeof 各型別大小(bytes)===" << std::endl;
    std::cout << "bool:\t\t" << sizeof(bool) << std::endl;
    std::cout << "char:\t\t" << sizeof(char) << std::endl;
    std::cout << "short:\t\t" << sizeof(short) << std::endl;
    std::cout << "int:\t\t" << sizeof(int) << std::endl;
    std::cout << "long:\t\t" << sizeof(long) << std::endl;
    std::cout << "long long:\t" << sizeof(long long) << std::endl;
    std::cout << "float:\t\t" << sizeof(float) << std::endl;
    std::cout << "double:\t\t" << sizeof(double) << std::endl;
    std::cout << "long double:\t" << sizeof(long double) << std::endl;

    // sizeof 也可以用在變數上
    int myVar = 42;
    std::cout << "\n變數 myVar 的大小:" << sizeof(myVar) << " bytes" << std::endl;

    // ══════════════════════════════════════════
    // 2. numeric_limits — 查看各型別的值範圍
    // ══════════════════════════════════════════
    std::cout << "\n=== 整數型別範圍 ===" << std::endl;

    std::cout << "short:\t\t"
              << std::numeric_limits<short>::min() << " ~ "
              << std::numeric_limits<short>::max() << std::endl;

    std::cout << "int:\t\t"
              << std::numeric_limits<int>::min() << " ~ "
              << std::numeric_limits<int>::max() << std::endl;

    std::cout << "long:\t\t"
              << std::numeric_limits<long>::min() << " ~ "
              << std::numeric_limits<long>::max() << std::endl;

    std::cout << "long long:\t"
              << std::numeric_limits<long long>::min() << " ~ "
              << std::numeric_limits<long long>::max() << std::endl;

    std::cout << "\n=== unsigned 型別範圍 ===" << std::endl;

    std::cout << "unsigned short:\t\t"
              << std::numeric_limits<unsigned short>::min() << " ~ "
              << std::numeric_limits<unsigned short>::max() << std::endl;

    std::cout << "unsigned int:\t\t"
              << std::numeric_limits<unsigned int>::min() << " ~ "
              << std::numeric_limits<unsigned int>::max() << std::endl;

    std::cout << "unsigned long long:\t"
              << std::numeric_limits<unsigned long long>::min() << " ~ "
              << std::numeric_limits<unsigned long long>::max() << std::endl;

    std::cout << "\n=== 浮點數型別資訊 ===" << std::endl;

    std::cout << "float:" << std::endl;
    std::cout << "  最小正值:" << std::numeric_limits<float>::min() << std::endl;
    std::cout << "  最大值:  " << std::numeric_limits<float>::max() << std::endl;
    std::cout << "  有效位數:" << std::numeric_limits<float>::digits10 << std::endl;

    std::cout << "double:" << std::endl;
    std::cout << "  最小正值:" << std::numeric_limits<double>::min() << std::endl;
    std::cout << "  最大值:  " << std::numeric_limits<double>::max() << std::endl;
    std::cout << "  有效位數:" << std::numeric_limits<double>::digits10 << std::endl;

    // ══════════════════════════════════════════
    // 3. 整數型別詳細示範
    // ══════════════════════════════════════════
    std::cout << "\n=== 整數型別 ===" << std::endl;

    short s = 32767;
    int i = 2147483647;
    long l = 2147483647L;             // L 後綴表示 long
    long long ll = 9223372036854775807LL;  // LL 後綴表示 long long

    std::cout << "short s = " << s << std::endl;
    std::cout << "int i = " << i << std::endl;
    std::cout << "long l = " << l << std::endl;
    std::cout << "long long ll = " << ll << std::endl;

    // unsigned 型別:只能存正數,範圍加倍
    unsigned int ui = 4294967295U;    // U 後綴表示 unsigned
    std::cout << "unsigned int ui = " << ui << std::endl;

    // ══════════════════════════════════════════
    // 4. 整數溢位(Overflow)
    // ══════════════════════════════════════════
    std::cout << "\n=== 整數溢位 ===" << std::endl;

    short maxShort = std::numeric_limits<short>::max();  // 32767
    std::cout << "short 最大值:" << maxShort << std::endl;

    // 溢位:超過最大值會回繞到最小值(未定義行為,但實務中通常回繞)
    short overflowed = static_cast<short>(maxShort + 1);
    std::cout << "short 最大值 + 1 = " << overflowed << " (溢位!)" << std::endl;

    // unsigned 溢位:回繞是明確定義的
    unsigned int zero = 0;
    unsigned int underflowed = zero - 1;  // 回繞到最大值
    std::cout << "unsigned 0 - 1 = " << underflowed << " (回繞!)" << std::endl;

    // ══════════════════════════════════════════
    // 5. 浮點數型別
    // ══════════════════════════════════════════
    std::cout << "\n=== 浮點數型別 ===" << std::endl;

    float f1 = 3.14f;         // f 後綴表示 float
    double d1 = 3.14159265358979;
    long double ld1 = 3.14159265358979323846L;  // L 後綴表示 long double

    std::cout << "float:       " << f1 << std::endl;
    std::cout << "double:      " << d1 << std::endl;
    std::cout << "long double: " << ld1 << std::endl;

    // 浮點數精度問題
    std::cout << "\n=== 浮點數精度陷阱 ===" << std::endl;
    double sum = 0.1 + 0.2;
    std::cout << "0.1 + 0.2 = " << sum << std::endl;
    std::cout << "0.1 + 0.2 == 0.3? " << std::boolalpha << (sum == 0.3) << std::endl;
    std::cout << "(浮點數無法精確表示某些十進位小數)" << std::endl;

    // ══════════════════════════════════════════
    // 6. 字元型別(char)
    // ══════════════════════════════════════════
    std::cout << "\n=== 字元型別 ===" << std::endl;

    char ch1 = 'A';
    char ch2 = 65;     // ASCII 碼 65 = 'A'
    // 跳脫字元也是 char
    std::cout << "'\\n' 的 ASCII 碼:" << static_cast<int>('\n') << std::endl;

    std::cout << "ch1 = '" << ch1 << "' (ASCII: " << static_cast<int>(ch1) << ")" << std::endl;
    std::cout << "ch2 = '" << ch2 << "' (ASCII: " << static_cast<int>(ch2) << ")" << std::endl;
    std::cout << "'0' 的 ASCII 碼:" << static_cast<int>('0') << std::endl;
    std::cout << "'a' 的 ASCII 碼:" << static_cast<int>('a') << std::endl;
    std::cout << "'A' 的 ASCII 碼:" << static_cast<int>('A') << std::endl;

    // 字元運算(因為本質上是整數)
    char next = ch1 + 1;  // 'B'
    std::cout << "'A' + 1 = '" << next << "'" << std::endl;

    // ══════════════════════════════════════════
    // 7. 布林型別(bool)
    // ══════════════════════════════════════════
    std::cout << "\n=== 布林型別 ===" << std::endl;

    bool t = true;
    bool f = false;

    std::cout << "true 的數值:" << static_cast<int>(t) << std::endl;   // 1
    std::cout << "false 的數值:" << static_cast<int>(f) << std::endl;  // 0

    // 非零整數轉 bool 為 true,零轉為 false
    bool fromInt = 42;     // true
    bool fromZero = 0;     // false
    std::cout << "42 轉 bool:" << std::boolalpha << fromInt << std::endl;
    std::cout << "0 轉 bool:" << std::boolalpha << fromZero << std::endl;

    // ══════════════════════════════════════════
    // 8. 隱式型別轉換(Implicit Conversion)
    // ══════════════════════════════════════════
    std::cout << "\n=== 隱式型別轉換 ===" << std::endl;

    // 安全的提升(小型別 → 大型別)
    int intVal = 42;
    double doubleVal = intVal;  // int → double,無精度遺失
    std::cout << "int → double: " << intVal << " → " << doubleVal << std::endl;

    // 危險的縮小(大型別 → 小型別)
    double pi = 3.99;
    int truncated = pi;         // double → int,小數被截斷
    std::cout << "double → int: " << pi << " → " << truncated << " (截斷!)" << std::endl;

    // 整數除法 vs 浮點數除法
    std::cout << "\n整數除法:7 / 2 = " << (7 / 2) << std::endl;
    std::cout << "浮點除法:7.0 / 2 = " << (7.0 / 2) << std::endl;

    // 混合運算:int 與 double 運算,int 會自動提升為 double
    int a = 5;
    double b = 2.0;
    std::cout << "5 (int) + 2.0 (double) = " << (a + b) << " (結果為 double)" << std::endl;

    // ══════════════════════════════════════════
    // 9. 明確型別轉換(static_cast)
    // ══════════════════════════════════════════
    std::cout << "\n=== static_cast 明確轉換 ===" << std::endl;

    double price = 19.99;
    int rounded = static_cast<int>(price);
    std::cout << "static_cast<int>(19.99) = " << rounded << std::endl;

    // 用 static_cast 解決整數除法問題
    int numerator = 7;
    int denominator = 2;
    double division = static_cast<double>(numerator) / denominator;
    std::cout << "7 / 2(使用 static_cast)= " << division << std::endl;

    // char ↔ int 轉換
    char letter = 'A';
    int ascii = static_cast<int>(letter);
    std::cout << "'" << letter << "' 的 ASCII 碼:" << ascii << std::endl;

    int code = 90;
    char character = static_cast<char>(code);
    std::cout << "ASCII " << code << " 對應字元:'" << character << "'" << std::endl;

    // ══════════════════════════════════════════
    // 10. 固定寬度整數型別(C++11, <cstdint>)
    // ══════════════════════════════════════════
    std::cout << "\n=== 固定寬度整數型別 ===" << std::endl;

    int8_t   i8  = 127;
    int16_t  i16 = 32767;
    int32_t  i32 = 2147483647;
    int64_t  i64 = 9223372036854775807LL;

    std::cout << "int8_t:  " << static_cast<int>(i8) << " (" << sizeof(i8) << " byte)" << std::endl;
    std::cout << "int16_t: " << i16 << " (" << sizeof(i16) << " bytes)" << std::endl;
    std::cout << "int32_t: " << i32 << " (" << sizeof(i32) << " bytes)" << std::endl;
    std::cout << "int64_t: " << i64 << " (" << sizeof(i64) << " bytes)" << std::endl;

    // 這些型別保證在所有平台上大小一致
    std::cout << "(固定寬度型別確保跨平台一致性)" << std::endl;

    return 0;
}

Articles liés