close
C 語言教學 - 13 - 使用變數 - 整數的基本運算

對於一個變數的應用來說,如果我們只會對他設定一個數值的話,實用性也沒有多高, 如果我們能夠使用變數來進行一些計算的話就更好了! 因此這次我們將來解說有關整數變數的一些基本運算。

賦值

我們可以使用一個等號「=」來設定一個變數的內容,我們之前在解說變數宣告的時候已經偷偷用過了! 例如:

a = 7;

這個敘述中我們就使用一個等號來把7這個數字設定給了變數a。

但是這裡要提一個很重要的觀念就是,C語言的等號和數學上的等號意義是完全不同的。 在數學中,等號表達其左邊與右邊的東西為相等; 但是在C語言,等號表達要做一件事情,就是把它右邊的東西丟給左邊的東西存起來。 所以我們若把上面的敘述換成下面這樣的話是不能編譯通過的:

7 = a;

上面敘述的意義就是要我們把a的內容取出來,然後傳給7,叫7把它存起來; 但因為7是個常數而不是變數,因此這個敘述將導致編譯的失敗。

看看另外一個常見的累加例子:

a = a + 1;

如果你要用數學的等號來看待這個敘述的話,就不容易明白他的行為, 讓我們以前面所說的邏輯來看看這個敘述做了什麼事:

  1. 首先,我們先假設在執行這個敘述之前a的值為3。
  2. 程式會先計算右邊的a+1,這時他會把a的內容讀出(3),然後和1相加,得出4。
  3. 再把這個計算的結果(4)丟給等號左邊的變數a儲存。
  4. 因此,在執行完這整個敘述後,a的值會變成4(在此之前a是3)。

希望藉由上面兩個例子可以充份的解釋C語言等號的真正作用。 因為同一個符號在數學上和程式語言上的意義大不同, 因此我們常稱呼程式語言的等號為「賦值」,而不是「相等」。

學會變數的賦值,我們就可以在程式執行過程中不斷的改變變數的內容、記錄我們感興趣的資料, 使程式真正能夠成為活動的程式。

變數的運算

這一部份要教你如何使用變數進行一些簡單的數學計算。 與賦值符號的容易混淆不同,基本數學運算這一部份與我們中小學學過的數學計算相似度非常高, 幾乎只要記得加(+)、減(-)、乘(*)、除(/)、和取餘(%),其他都和大家從前學的觀念一樣。 我們看看幾個例子:

int a=13, b=4, r;

r = a + b;  // 相加,最後的r就是17。
r = a - b;  // 相減,最後的r就是9。
r = a * b;  // 相乘,最後的r就是52。
r = a / b;  // 相除,比較完整的說法是取a除以b的商數,最後的r就是3。
r = a % b;  // 取餘,就是取a除以b的餘數,最後的r就是1。

最後再加個正負號的操作,例如:

r = -b;  // 取負的b,最後r變成-4。
r = +a;  // 取正的a,最後r變成13。

// 另外請注意正負號的操作和數學上的理解是一致的,所以:

int c = -3;
r = -c;  // 取負的c,負負得正,最後r變成3。
r = +c;  // 取正的c,最後的r仍然是-3。

這裡還要注意到一個重要的地方! 我們會發現同樣是「-」符號,使用在不同的地方會產生不同的意義,一個是「相減」、一個是「取負值」。 C語言擁有很多這樣功能不同但名稱相同的的同名運算子、甚至是同名關鍵字, 同樣的符號會依據不同的上下文而可能被解釋成完全不同的東西。

對於運算子的介紹就先到這邊為止。 事實上,C語言的運算子有數十個,分為不同種類。 但是我不會在這裡講解全部的運算子,理由是一樣的,第一是目前還用不到,第二是初學者也吸收不了。 若你真的迫不及待想要看看全部的運算子都有哪些,可以參閱維基百科: https://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B

運算子的優先順序

不知道讀者有沒有這樣的疑問,當我們在一個表達式裡面寫上多個運算子時,電腦會先算哪個後算哪個呢? 我們先以下面這個大家比較熟悉的類數學算式來舉例:

answer = 3 + 6 * 9 + 7 / -5;  // 這裡出現了「+」、「-」、「*」、「/」、和「=」5個符號6個運算子(減和取負是同一個符號),
                              // 這裡取負值出現在最後,但優先性卻是最高的,於是會首先被處理。
                              // 所以5會先變成負5,然後才進行乘除運算。
                              // 所以這個算式會先變成下面這樣:
answer = 3 + 54 - -1;  // 現在要來算加減了,加減的地位是一樣的,於是由左至右計算(注意其他等級的運算子不一定是由左至右)。
answer = 57 - -1;
answer = 58;  // 現在只剩下等號了。沒錯,賦值的優先順序是很低的,在我們這個算式中它最後才被處理。
              // 當賦值運算處理完成後,變數asnwer的內容值就會被存為58。
              // 至此,整個算式運算完畢。

由上面的範例我們大概可以注意到幾點:

  1. 運算子們分成了很多群組,每個群組都有一個優先等級,優先等級比較高的會比優先等級比較低的先被處理。
  2. 如果是優先等級相同的運算子,則可能由左至右、或由右至左依序處理,這會依據該群組的規定決定。

若有時候遇到有些運算子的優先順序比較低,但我們卻希望它先被處理的狀況時該怎麼辦呢? 這時圓括弧(「(」和「)」)的功能就派上用場了!

answer = 2*( 4 + 3 );

和數學式類似,使用括弧把某一部份包起來的話可以強制該部份先被處理。 以上面的算式為例,雖然加號的優先順序比成號低,但因為加上了括弧,所以實際上4+3會先被計算。 當然,括弧內如果有很多運算子的話,括弧內部也是依據其優先順序進行運算的,與數學式一樣。

括弧也可以嵌套使用,但不同於數學上我們會使用小括弧、中括弧、大括弧,在C語言裡只使用圓括弧(小括弧),像下面這樣:

answer = ( 2*( 4 + 3 ) + 6*( 5 - 4 ) * 9/( 1 + 2 ) )*3 + 7;

括弧除了用來強制優先運算外,也可以更清楚的強調運算的順序。 意思就是所以當我們遇到比較不熟悉的運算時,若我們希望這個運算先做,卻不是很確定這個運算原生的優先順序時, 就可以加上括弧來確保它一定會先被計算,而不用不斷的查詢、甚至背誦C語言一卡車的運算子特性。 以下面的算式做為例子:

answer = 3*4 + 5*-8 + 7*6;

比如說當我們希望中間的5乘上負8在運算時,先對8取負值,然後才做乘法。 若我們不卻定程會先被運算還是取負會先被處理的話,就可以加上括弧,如下:

answer = 3*4 + 5*(-8) + 7*6;

當然,熟按四則運算的各位一定會知道取負一定會比乘除優先運算,這裡只是使用我們學過的運算子做為例子而已。

運算子補充知識

C語言運算子的行為基本上就是: 把運算子左邊、或右邊、或左右兩邊的東西抓起來進行某種處理後,再傳回某種東西。 統整來說,各種不同運算子之間的差異主要分為幾點:

  1. 運算子會抓哪些位置的物件來進行處理?
  2. 運算子會對物件進行什麼處理?
  3. 運算子會傳回什麼東西?

比方說加號就是把加號左右兩邊的東西抓起來計算,並傳回他們相加之後的結果。 以下面這個簡單的算式做為說明:

ans = a + b + c;

若使用圓括弧來強調上面計算式原來的運算順序的話,上面的式子就等同於:

( ans = ( ( a + b ) + c ) );

注意到我把最外層也加上了括弧,目的是提醒、以及強調賦值符號本身也是一個運算子。 所以依照運算的順序,程式會先處理第一個加號,也就是a和b中間的加號。 加號會把左右兩邊的東西取來運算,於是a和b被取來計算。 最後這個運算子傳回了它們兩個東西相加後的結果,實際上這是一個暫時的變數, 但為了方便我們的教學,我們假設這個加號會傳回一個T1。 在處理完第一個加號後,計算式變成了:

( ans = ( T1 + c ) );

於是接下來就是進行第二個加號的計算,這個加號取了T1和c,並傳回他們相加後的結果,假設為T2:

( ans = T2 );

最後,進行賦值運算子的計算,它把右邊的東西,也就是T2,傳遞給左邊的ans。 那麼賦值運算子也回傳回東西嗎?沒錯,賦值運算子也會傳回東西,他傳回的是運算子左邊最終的結果。 以上面例子來說,賦值號先把它右邊的T2存到ans變數去,然後傳回ans,並且是已經被變更過的ans。 因此,就產生了一些比較花俏的應用,例如:

a = b = 3 + 1;

其等同於:

( a = ( b = ( 3 + 1 ) ) );

最後b會變成4的結果應該不用再多做解釋,然而讓b變成4的那個賦值符號會傳回最後的b結果, 而這個結果會後面的運算子拿來使用,也就是:

( a = ( 4 ) );

因此最後a也變成4了! 當然第二個賦值符號仍然會傳回a最後的內容4,只是因為後面不再有其他的計算需要處理, 因此這最後的回傳值就被忽略掉了。

這種應用最常見的用法是像下面這樣:

a = b = c = 3;

這樣子就可以用一個陳述式來把a、b、c三個變數的值都設成3。 但是這種連續賦值的寫法有時候並不利於閱讀,因此有時這樣的寫法並不被推薦使用。

重點回顧

  • 等號「=」在C語言裡並不是指真正的「相等」,而是「賦值」,即把等號右邊的東西丟給左邊的東西存起來。
  • C語言有許多長相相同但意義隨上下文而完全不同的符號,初學者在寫作或閱讀程式時需要多注意。
  • C語言眾多的運算子被分成很多群組,每個群組都有一個優先等級。 當一個表達式裡面同時出現多個運算子時,優先等級比較高的會比優先等級比較低的先被處理。
  • 對於優先等級相同的運算子,則可能由左至右、或由右至左依序處理,這會依據該群組的規定決定。
  • 使用圓括弧可以強制指定某個部份先進行運算,也可以用來強調、或確保某些我們不清楚其運算順序的地方會先被處理。
  • 如果沒有特別的原因,儘量避免使用花俏的連續賦值寫法。

練習與討論

試著寫一個程式,使用幾個變數來設定一個圓形的直徑、一個正方形的一邊長、以及一個長方形的長和寬。 然後計算並顯示這三個幾何形狀的周長、以及面積。

arrow
arrow
    全站熱搜

    夜行者 發表在 痞客邦 留言(0) 人氣()