CodeGym /課程 /C++ SELF /C++ 的基本類型:int、long、unsigned、char

C++ 的基本類型:int、long、unsigned、char

C++ SELF
等級 6, 課堂 2
開放

1. 引言

當一個人剛開始學程式時,常常會這麼想:「我只是要存放數值,為什麼不能做一個通用的類型 number 就好?」這很正常:大腦在節省能量。但 C++ 是一門喜歡具體化的語言。類型在 C++ 中不是「裝飾」,而是一個約定:需要多少記憶體、哪些值是允許的、輸入/輸出如何運作、以及哪些運算有意義。

想像你把資料放在不同的盒子裡。餅乾用有蓋的盒子,湯用鍋子,空氣…好吧,空氣不能存放,它就像週五晚上的動力一樣會消失。類型就像不同的「容器」,如果你試圖把湯倒進餅乾盒,結果可預期地會很糟。

今天我們會拆解五種常見的基本類型:

  • int — 普通有號整數,
  • long long — 較大的整數,
  • unsigned — 無符號整數,
  • double — 浮點數類型,
  • char — 單一字元。

同時我們會引入一個很重要的概念:值域(類型能表示的最小與最大邊界)。

類型的大小

與許多程式語言不同,C++ 的整數類型沒有固定大小。這樣設計是為了讓編譯器能與平台(作業系統+處理器)更好地對應。

同一個 C++ 程式可以編譯到 16、32、64 位元的處理器;在 macOS、Windows、Linux 等不同平臺下執行。而它們的整數類型各不相同(這是歷史的結果)。

最初 C++ 有三個整數類型:

  • int - 整數類型
  • short int(也就是 short)- 短整數類型(約為 int 的一半)
  • long int(也就是 long)- 長整數類型(約為 int 的兩倍)

之後又加入了更長的整數 - long long int,即 long long。

目前它們的「常見」長度通常如下:

類型 Windows x64 macOS x64
short
2 位元組 2 位元組
int
4 位元組 4 位元組
long
4 位元組 8 位元組
long long
8 位元組 8 位元組

與其使用 long,通常更建議使用 long long — 它能更確定地比 int 大。

如何根據需求選擇類型

很多人會按「寫起來比較短」或「看到範例這樣寫」來選擇類型。但在真實程式碼中,類型本身就是語意的一部分。如果你在程式中看到 bool isAdmin,你幾乎不需要註解就能理解那裡只有兩種狀態。看到 char grade,你會預期像 'A' 或 'B' 之類的字元。如果把一切都用 int,就會變成「垃圾場」:0 可能代表「否」、「錯誤」、「未找到」、「第一個元素」或「尚未輸入」。

2. 整數類型:int、long long、unsigned

int:基本的整數「磚塊」

int 是最常用的整數類型,通常是學習者的起點。當你計算已解題數、天數編號、迴圈計數器、攝氏溫度(無小數)或遊戲分數時,int 幾乎總是足夠的。

有兩件事要理解。第一:int 儲存的是整數,且可以表示負數。第二:int 不是無限的 — 它有邊界,這對理解「值域」很重要。但目前先以實務角度看:int 是「合理大小整數的預設選擇」。

給我們的 StudyBuddy 的一個小範例:

#include <iostream>

int main() {
    int tasksSolvedToday = 0;
    std::cin >> tasksSolvedToday;

    std::cout << tasksSolvedToday << '\n'; // 例如:7
}

這裡 tasksSolvedToday 表示「數量」,語意上是整數。在這個層次上類型能幫助避免誤把 3.14 這種小數存進去 — 編譯器會阻止(這是件好事)。

long long:當數值真的很大時

幾乎每個專案都會遇到某個時刻,普通的 int 不夠用了。通常不是一下子,而是當你開始累積數值:一年的總秒數、總觀看次數、總資料量、賽季總分、日誌操作次數 — 也就是會遠超「一般輸入數字」的情況。

long long 是用於大型整數的類型。它也能表示負數,但重要的是它能儲存比 int 大得多的值。我們現在不必記住精確邊界(那取決於平臺),但要記住這個理念:long long 用於重要且大的數值。

在 StudyBuddy 中加入「歷史總解題數」(讓使用者輸入至今已解題數,程式計算新總和):

#include <iostream>

int main() {
    long long totalTasksBefore = 0;
    int tasksToday = 0;

    std::cin >> totalTasksBefore >> tasksToday;
    long long totalAfter = totalTasksBefore + tasksToday;

    std::cout << totalAfter << '\n'; // 例如:1050
}

注意這點:每天的輸入可能很小,但累計後會很大。這是常見模式,與會不會寫公式無關,而是關於正確選擇類型。

unsigned:把「負號」從約定裡移除

在 C++ 中,任何整數類型都可以透過加上關鍵字 unsigned 變成無符號(非負)。unsigned int(常寫作單純的 unsigned)表示:「整數且不允許負值」。也就是說,unsigned 的值域會往較大的正數偏移,因為不需要保留位元來表示負號。

對於「數量」這類問題:題目數、使用者數、嘗試次數,聽起來很理想。但要注意一個實務面的問題:程式中有時會用負數作為特殊標誌(例如「錯誤」或「未找到」)。如果你把類型轉成無符號,這種做法就不適用了。目前的簡單規則是:只有當你確信從語意上絕不會有負值,且不需要用負值當特殊信號時,才使用 unsigned。

在 StudyBuddy 中加入「連續學習天數」 — 這是個很適合用非負值表示的例子:

#include <iostream>

int main() {
    unsigned streakDays = 0;
    std::cin >> streakDays;

    std::cout << streakDays << '\n'; // 例如:12
}

目前足以記住:unsigned 在型別上強調「非負」。但這不是「萬能的保護」,只是更嚴格的約定。

3. 小數與字元類型:double 與 char

double:當數字有小數部分時

如果 int 與 long long 是針對整數,double 則是針對帶有小數部分的數字。當題目出現平均值、百分比、係數、帶小數的溫度或帶分角的金額時,整數類型就不夠了。

double 儲存浮點數。它能表示像 3.14、0.5、-12.75 這樣的值。但為了這個彈性,你需要付出代價:這些數在內部以二進位表示,不會是「完美精確」,可能會有小幅誤差。

在 StudyBuddy 中加入一週的平均每日產能:

#include <iostream>

int main() {
    double averageTasksPerDay = 0.0;
    std::cin >> averageTasksPerDay;

    std::cout << averageTasksPerDay << '\n'; // 例如:5.75
}

注意 0.0 — 這表示我們正在處理浮點數。

為何不能只用 int「巧妙地除法」?因為整數除法會捨棄小數部分。例如, 7 / 2 在整數運算中會得到 3,而不是 3.5。如果你需要包含小數的精確結果,就必須使用 double。

也要明白:double 並非「無限精確」的計算器。舉例來說,數字 0.1 在二進位系統中無法精確表示,所以像 0.1 + 0.2 的結果可能是 0.30000000000000004。這不是編譯器的錯,而是浮點表示法的特性。

給新手的實務規則:

  • 如果你在計算整數數量(件數、天數、元素)— 使用 int 或 long long;
  • 如果你在計算平均值、百分比、係數、小數— 使用 double。

double 表示一個約定:「這裡允許小數值」。和其他類型一樣,它在變數宣告層面就幫助讓程式更易懂。

char:一個字元,以及 'A' 與 "A" 的差別

char 是用來儲存單一字元的類型。它用單引號表示:'A'、'?'、'7'。這與字串 "A"(字串可以包含多個字元,在 C++ 中通常使用 std::string)是本質不同的。

對初學者來說很實用的習慣:看到單引號就想到「一個字元」。看到雙引號就想到「字串/文字」。

在 StudyBuddy 中我們會讓使用者輸入一個單字母的「生產力評等」,例如 A、B、C:

#include <iostream>

int main() {
    char grade = 'C';
    std::cin >> grade;

    std::cout << grade << '\n'; // 例如:A
}

char 非常適合單字元資料:回應代碼 Y/N、評等 A/B/C、退出指令 q、分隔符或單一分類字元。

內部上 char 實際上儲存的是字元代碼,本質上也可以視為一種整數類型,在 C++ 中可以對它做算術運算。

5. 值域(範圍)

現在到本講最重要的哲學性部分 — 但我們會以最實務的方式處理。

電腦在記憶體中儲存資料。記憶體是有限的。因此可以寫入變數的不同值的數量也是有限的。由此得出一個簡單觀念: 每個整數類型都有最小值與最大值。這就是所謂的 值域。

在日常生活中,這類似於老車的里程表:它不是無限的,當數字用盡時它會「回繞」(有時甚至壞掉)。類型也是類似的想法:超出邊界時程式行為會變得不正確。我們現在不打算深入「會如何不正確」的細節(那是另一個主題),但你今天就應該養成這個習慣:選擇類型時要確保值能正確儲存。

為了方便判斷,下面是現代系統上一張實務參考表。這不是「處處保證」,而是心智上的良好指南:

類型 儲存內容 範例值域
bool
true/false
false / true (0 或 1)
char
單一字元 −128 … 127
int
有號整數 −2 147 483 648 … 2 147 483 647
unsigned
無符號整數 0 … 4 294 967 295
long long
大型有號整數 −9 223 372 036 854 775 808 … 9 223 372 036 854 775 807
double
有號浮點數 約 ±1.7 × 10308(約 15 位有效數字)

要帶走的概念是:若你在計算「總和」、「累計數量」、「累積秒數」等,通常是 long long 的候選。如果是「旗標/是非題」,使用 bool。若是「單一字母/命令」,使用 char。

6. 類型大小與 sizeof

我們已談到 C++ 的整數類型 沒有固定大小,長度取決於平台與編譯器。那如何查出在當前機器上某個類型的實際大小?

可以使用運算子 sizeof。它會回傳型別或變數佔用的位元組數。

一個最簡單的範例:

#include <iostream>

int main() {
    std::cout << sizeof(int) << '\n';
    std::cout << sizeof(long long) << '\n';
    std::cout << sizeof(double) << '\n';
    std::cout << sizeof(char) << '\n';
}

例如你可能會得到:

4
8
8
1

這表示:

  • int 佔 4 位元組
  • long long 佔 8 位元組
  • double 佔 8 位元組
  • char 佔 1 位元組

7. 選擇基本類型時的常見錯誤

錯誤 #1:用 int 來存邏輯狀態並製造「魔法數字」。
初學者常寫 int ok = 1;、int ok = 0;,然後在別處突然寫出 if (ok == 2)。問題不是編譯器看不懂,而是人會失去理解。若狀態只有兩個選項,使用 bool 能直接在類型上表達,並避免你「不小心」引入第三種狀態。

錯誤 #2:把 char 當成「短字串」。
有時會想把 "OK" 或 "Hi" 存到 char,因為「只有兩個字元」。但 char 是正好一個字元。如果你需要兩個字元,應使用字串(std::string)。每次問自己:「我需要一個字元,還是文字?」這是個好習慣。

錯誤 #3:把 unsigned 當成教條,因為「數量不會為負」,結果卻又需要負數。
現實很狡猾:今天你存的是「題目數」,明天你可能想用負數表示「未輸入」、「錯誤」或「未找到」。因此一開始不要把 unsigned 視為信仰:只有在確定永遠不會需要負值或負值作為特殊標誌時才使用它。

錯誤 #4:把累計總和存成 int,因為「目前還夠用」。
這是一個經典陷阱。測試資料小時一切正常,之後當你計算「全年」、「累積到目前為止」、「所有使用者的總和」時,數值可能超出範圍。這就是為什麼累計與總和常提前用 long long:這是一個便宜的保險,能省下大量找錯時間。

錯誤 #5:認為值域是「某種理論」,而完全忽視它。
值域不是學術議題,而是記憶體有限的直接結果。如果類型無法表示所需的值,程式即會出錯。即使你現在還不會手算邊界,養成問自己「這個數可能會變得很大嗎?」的習慣,就能讓你更有意識地選擇類型。

1
任務
C++ SELF, 等級 6, 課堂 2
上鎖
類型規格
類型規格
1
任務
C++ SELF, 等級 6, 課堂 2
上鎖
同意回覆
同意回覆
1
任務
C++ SELF, 等級 6, 課堂 2
上鎖
貨物批次
貨物批次
1
任務
C++ SELF, 等級 6, 課堂 2
上鎖
秒數與 int
秒數與 int
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION