C語言的賦值徹底解析!從基礎到進階,適合初學者

目次

1. C語言的賦值是什麼?

C語言的程式設計中,賦值是基礎中的基礎,同時也是非常重要的操作。賦值用於將值設定給變數。這是程式能如預期運作的第一步。 例如,請看以下程式碼。
int a = 5;
此程式碼定義了整數型變數 a,並將值 5 賦給它。如此,賦值表示將變數與值相關聯的操作。

賦值的目的

  • 資料的保存:將在程式中使用的資料儲存起來。
  • 操作的準備:以儲存的資料為基礎進行計算或處理。

如果沒有賦值會怎樣?

如果賦值未正確執行,變數會被儲存稱為「未定值」的無效值,程式的運作可能會產生意外的結果。

2. 代入運算子的基礎

進行賦值的基本手段是「賦值運算子」。在 C 語言中,最基本的賦值運算子是 =

賦值運算子的原理

賦值運算子會將右側的值指派給左側的變數。以下示範具體例子。
int x = 10;  // 將 10 賦給 x
int y = x;   // 將 x 的值賦給 y(y 變成 10)
在上述例子中,先將值 10 賦給 x,之後將 x 的值賦給 y

複合賦值運算子

在 C 語言中,為了更有效率的賦值,提供了複合賦值運算子。藉此可以在運算值的同時同時進行賦值。
  • 形式: +=, -=, *=, /=, %=
  • 範例
int a = 5;
a += 3;  // 與 a = a + 3 同義(a 的值變成 8)
a *= 2;  // 與 a = a * 2 同義(a 的值變成 16)
使用複合賦值運算子,可以讓程式碼更簡潔。

位元運算的賦值運算子

在 C 語言中,位元操作也可以使用賦值運算子。
  • 形式: &=, |=, ^=
  • 範例
int b = 6;  // 6 的二進位是 110
b &= 3;     // b = b & 3(b 的值是二進位 010,也就是 2)
位元操作在操作特定位元時非常便利。

3. 初始化與賦值的差異

在 C 語言中,「初始化」與「賦值」看似相似卻是不同的概念。透過了解各自的角色,能夠更有效率地設計程式。

初始化是

初始化是指在定義變數的同時為該變數設定值的操作。換句話說,就是「在建立變數的同時賦予值」的過程。

初始化的範例

int x = 10;  // 變數 x 定義,並同時設定值 10
float y = 3.14;  // 為 y 設定浮點數值
在此範例中,xy 兩者在宣告的同時即被設定了值。

初始化的特點

  • 僅在宣告時執行一次。
  • 雖非必須,但為避免未初始化變數,建議這樣做。

賦值是

賦值是指對已宣告的變數設定新值的操作。與初始化不同,這可以在程式中執行任意次數。

賦值的範例

int x;  // 定義變數 x(尚未初始化)
x = 5;  // 將值 5 賦給 x
x = 10; // 將 x 的值改為 10
在此範例中,先宣告 x,再賦值 5,之後再賦值 10

賦值的特點

  • 可在初始化之後或程式中任意時機執行。
  • 可對同一變數多次更新值。

初始化與賦值的差異

項目初始化賦值
時機僅在宣告時可在程式任意位置執行
次數僅一次可多次
必要性非必要但建議執行視情況而定需要
範例int a = 10;a = 20;

結合初始化與賦值的範例

以下為結合初始化與賦值的程式碼範例。
#include <stdio.h>

int main() {
    int a = 5;  // 初始化
    printf("初始值: %d\n", a);

    a = 10;  // 賦值
    printf("新值: %d\n", a);

    return 0;
}
輸出結果
初始值: 5
新值: 10

初始化與賦值的使用分別

  1. 適合使用初始化的情況
  • 在宣告變數後立即設定值的情況。
  • 想防止未初始化變數導致的錯誤時。
  1. 適合使用賦值的情況
  • 需要在之後更新初始值的情況。
  • 想在迴圈內動態變更值的情況。

4. 賦值與等價運算子之差異

C語言中,賦值運算子(=)與等價運算子(==)各自有不同的目的。然而,因為符號相似容易混淆,是初學者常犯的錯誤之一。本節將詳細說明它們的差異與正確的使用方式。

賦值運算子(=)是什麼

賦值運算子用於將右側的值賦給左側的變數。這是設定或更新變數值時使用的基本運算子。

賦值運算子範例

int x;
x = 10;  // 將變數 x 賦值為 10
在此範例中,x 被賦值為 10

注意事項

  • 賦值運算子用於「設定值」。
  • 可以連續執行多個賦值。
int a, b;
a = b = 5;  // 將變數 b 賦值為 5,之後將 b 的值賦給 a

等價運算子(==)是什麼

等價運算子用於比較左右兩側的值是否相等。比較結果以布林值(truefalse)回傳。

等價運算子範例

int x = 10, y = 20;
if (x == y) {
    printf("x與y相等n");
} else {
    printf("x與y不相等n");
}
此範例會檢查 xy 是否相等,並根據結果顯示不同的訊息。

注意事項

  • 等價運算子用於「比較值」。
  • 比較結果回傳真(1)或偽(0)。

賦值與等價混淆所引發的錯誤

若混淆賦值運算子與等價運算子,可能導致程式行為不如預期。以下是典型範例。

常見錯誤

int a = 5;
if (a = 10) {  // 使用了賦值運算子
    printf("條件被評估為真n");
}
在此範例中,a = 10 會將 10 賦給變數 a,結果使 if 條件被評估為「真」。

修正範例

int a = 5;
if (a == 10) {  // 使用等價運算子
    printf("a等於10n");
} else {
    printf("a不等於10n");
}

分辨賦值與等價的技巧

  1. 根據語境判斷
  • 若要設定變數的值,使用 =
  • 若要比較值,使用 ==
  1. 使用括號
  • 在條件式中使用賦值時,為了明確意圖,請以括號包住。
if ((a = 10)) {  // 這被視為明確的賦值
    // 條件為真時的處理
}
  1. 啟用編譯器警告
  • 啟用編譯器警告即可偵測未預期的賦值。

賦值與等價比較總結

項目賦值運算子(=)等價運算子(==)
角色將值設定到變數確認值是否相等
用途將值賦給變數在條件式中的比較
範例a = 10;a == 10
誤用的結果值被未預期地更改條件式未如預期運作

實作範例

以下程式碼示範正確區分賦值與等價的使用方式。
#include <stdio.h>

int main() {
    int a = 5, b = 10;

    // 使用等價運算子比較
    if (a == b) {
        printf("a與b相等n");
    } else {
        printf("a與b不相等n");
    }

    // 使用賦值運算子設定值
    a = b;
    printf("a的新值: %dn", a);

    return 0;
}
輸出結果
a與b不相等
a的新值: 10

5. 指標與賦值的關係

C 語言的特色功能之一「指標」與賦值有密切關係。了解指標對於記憶體操作與高效程式設計是不可或缺的。本節將詳細說明指標的基本概念與賦值之間的關聯。

什麼是指標

指標是一種特殊變數,用於儲存變數的位址(記憶體位置)。一般變數保存值本身,而指標則保存該值所在的位址。

指標的宣告與使用範例

int a = 10;
int *p;  // 宣告整數型指標 p
p = &a;  // 將 a 的位址賦給 p
此處將變數 a 的位址賦給指標 p。透過 p 可以間接操作 a 的值。

指標變數的賦值

在對指標變數賦值時,需要指定變數的位址。這需要使用位址運算子(&)。

使用位址運算子進行賦值

int b = 20;
int *q;
q = &b;  // 將 b 的位址賦給 q
在此範例中,指標 q 被賦予變數 b 的位址。q 作為指向 b 值的指標運作。

使用間接參照操作值

要透過指標操作變數的值,需要使用間接運算子(*)。使用間接運算子即可參照與修改指標所指向位址的值。

間接參照範例

int x = 30;
int *ptr = &x;

printf("x的值: %dn", x);  // 顯示 x 的值
*ptr = 50;  // 透過 ptr 修改 x 的值
printf("修改後的x的值: %dn", x);
輸出結果
x的值: 30
修改後的x的值: 50
此處透過指標 ptr 直接修改變數 x 的值。

指標的初始化與賦值注意事項

未初始化就使用指標是危險的。未初始化的指標指向未知位址,程式可能會出現未預期的行為。

未初始化指標範例

int *p;
*p = 10;  // 會導致錯誤

解決方案

  • 在使用指標前務必先初始化。
  • 未被初始化的指標請先賦值為 NULL
int *p = NULL;  // 以 NULL 初始化指標
if (p != NULL) {
    *p = 100;  // 可安全使用
}

使用指標在函式間傳遞值

指標在函式間傳遞值時也很有用。將指標傳遞給函式,可直接操作呼叫端的變數。

使用指標的函式範例

#include <stdio.h>

void updateValue(int *n) {
    *n = 42;  // 透過間接參照修改值
}

int main() {
    int num = 10;
    printf("修改前的值: %dn", num);
    updateValue(&num);  // 傳遞 num 的位址
    printf("修改後的值: %dn", num);

    return 0;
}
輸出結果
修改前的值: 10
修改後的值: 42
此處函式 updateValue 使用指標直接修改呼叫端的變數 num

6. 賦值時的注意事項

在 C 語言執行賦值操作時,為了得到正確的結果,需要注意幾點。特別是處理整數型別或指標時,需要特別留意。本節將詳細說明與賦值相關的主要注意事項。

1. 資料型別的相容性與型別轉換的必要性

範例:資料型別差異導致的問題

int a;
float b = 3.14;

a = b;  // 將浮點數賦值給整數型別
printf("a的值: %dn", a);  // 結果為 3(小數部分被截斷)
在此範例中,float 型的值在賦值給 int 型時,小數部分會被截斷。

解決方案:使用型別轉換

使用型別轉換(cast)可以有意地改變型別。
int a;
float b = 3.14;

a = (int)b;  // 明確的型別轉換
printf("a的值: %dn", a);  // 結果為 3
透過使用型別轉換,程式設計師可以明確表示其意圖的型別轉換。

2. 使用未初始化變數所造成的問題

如果變數未經初始化就使用,可能會包含不可預測的值(垃圾值)。使用此類變數進行賦值操作會導致意外的行為。

範例:使用未初始化變數

int x;
printf("x的值: %dn", x);  // 輸出未定義的值
未初始化的變數 x 內含隨機值,會使程式的行為難以預測。

解決方案:初始化變數

在宣告變數時同時進行初始化,即可防止此問題。
int x = 0;
printf("x的值: %dn", x);  // x的值為 0

3. 禁止對常數或唯讀變數賦值

使用 const 修飾子宣告的變數無法賦值。若嘗試對此類變數賦值,會產生編譯錯誤。

範例:對 const 變數賦值

const int a = 5;
a = 10;  // 編譯錯誤
透過 const 修飾子,變數 a 被視為唯讀。

解決方案

若需要更改值,可移除 const 修飾子,或改用其他變數。

4. 造成段錯誤的指標操作

在使用指標進行賦值時,若嘗試存取不正確的位址,會導致段錯誤(程式崩潰)。

範例:對無效指標賦值

int *p;
*p = 10;  // 對未初始化的指標賦值(可能導致崩潰)

解決方案

  • 初始化指標。
  • 先賦予有效位址再進行操作。
int x = 5;
int *p = &x;
*p = 10;  // 安全的賦值

5. 陣列與字串賦值的限制

在 C 語言中,無法直接對整個陣列或字串賦值。

範例:對陣列直接賦值

int arr1[3] = {1, 2, 3};
int arr2[3];
arr2 = arr1;  // 編譯錯誤

解決方案

使用 memcpy 函式來複製陣列內容。
#include <string.h>

int arr1[3] = {1, 2, 3};
int arr2[3];

memcpy(arr2, arr1, sizeof(arr1));  // 複製 arr1 的內容到 arr2

賦值時的注意事項總結

注意點概述解決方案
資料型別不匹配會發生非預期的值轉換或資訊遺失使用型別轉換
使用未初始化變數包含不可預測的值初始化變數
對 const 變數賦值唯讀的值無法賦值使用非 const 變數
不正確的指標操作存取無效位址徹底指標初始化
陣列與字串的賦值限制無法直接對整個陣列賦值使用 memcpy

7. 總結

本文全面解說了 C 語言中「賦值」的基本到應用。賦值是程式中不可或缺的操作,了解正確的使用方式可以防止錯誤,提升效率的編碼。本節將回顧本文並整理重要要點。

文章回顧

  1. 賦值運算子的基本
  • = 是將右側的值設定到左側變數的運算子。
  • 使用複合賦值運算子(+=、-= 等)可以讓程式碼更簡潔。
  1. 初始化與賦值的差異
  • 初始化在變數宣告時進行,賦值則是在宣告後改變值的操作。
  • 若忘記初始化,可能會因未定義的值而產生錯誤。
  1. 賦值與相等運算子的差異
  • 賦值運算子(=)設定值,而相等運算子(==)比較值是否相等。
  • 為防止混淆,需要正確理解語法。
  1. 指標與賦值
  • 使用指標可以直接操作變數的位址。
  • 若使用未初始化的指標或不正確的位址,程式會崩潰。
  1. 賦值時的注意事項
  • 資料型不匹配、未初始化變數、禁止對 const 變數賦值、不正確的指標操作等都會成為錯誤的原因。
  • 為防止這些情況,適當的初始化與型別轉換是很重要的。

適當的賦值操作的重要性

正確理解並善用賦值操作,可提升程式碼的可讀性與可維護性。此外,能夠事先防止錯誤與 Bug 的產生,提升程式的可靠性。

8. 常見問題(FAQ)

Q1. 在 C 語言中若未初始化變數就使用會發生什麼情況?

未初始化的變數會包含不確定值(垃圾值),會導致不可預測的行為。例如,在條件式中使用,可能會產生意外的結果。

Q2. 為什麼賦值運算子是「=」,相等運算子是「==」?

這是 C 語言設計上的規範。為了區分賦值與比較,設定「=」與「==」具有不同的意義。清楚了解這個差異非常重要。

Q3. 如何使用指標來修改變數的值?

使用指標時,將變數的位址指派給指標,並使用間接參照運算子(*)來修改值。例如:
int x = 10;
int *ptr = &x;
*ptr = 20;  // x的值被改為20

Q4. 複合賦值運算子的優點是什麼?

使用複合賦值運算子(例如:+=*=)可以讓程式碼更簡潔,提升可讀性。此外,減少冗長的寫法也能降低錯誤的可能性。

Q5. 位元運算的賦值運算子在什麼情況下使用?

位元操作(例如:&=|=)用於設定或清除位元遮罩,或操作特定的位元。特別適用於硬體控制與低階程式。