初始化
當你搬進一個新房間,你可以原封不動地接收前一位房客留下的樣子——堆滿不知名的雜物——或者你可以從一開始就清空它、按自己的方式佈置好。在 C 中,當一個變數誕生時它會得到一塊記憶體,而那塊記憶體可能保有原本就在那裡的殘餘位元。初始化就是在變數建立的那一刻給它一個已知的起始值,讓它絕不會握著垃圾。
你藉由在宣告中寫上等號與一個值來初始化,例如「int x = 5;」。對陣列與結構則用大括號,例如「int a[3] = {1, 2, 3};」。這裡有個取決於變數住在哪裡的關鍵差異。具有自動(區域)儲存期、而你沒有初始化的變數,會以不確定的值開始——在指派前讀取它是未定義行為。具有靜態或全域儲存期、而你沒有初始化的變數,則會由執行期啟動程式自動設為零。所以危險區是未初始化的區域變數。
為什麼重要:讀取未初始化的變數是 C 中最常見也最滑溜的錯誤之一,因為程式可能因運氣而看似正常運作(殘餘位元剛好合理),然後在另一台機器或另一次建構上神祕地失敗。安全的習慣是只要能做到,就在宣告時初始化變數。編譯器警告 -Wuninitialized 與 MemorySanitizer 這類工具,正是為了抓出這個問題而存在。
int total = 0; /* 初始化為已知值 */ int counts[4] = {0}; /* 四個元素全設為 0 */ int stray; /* 未初始化:握著垃圾 */ /* printf("%d", stray); 會是未定義行為 */
total 與 counts 以已知值開始;stray 是個未初始化的區域變數,因此讀取它是未定義行為。
只有靜態與全域變數會被自動歸零;未初始化的「區域」(自動)變數握著不確定的位元,讀取它們是未定義行為——並非只是一個隨機數。請盡可能在宣告時就初始化。