1. 程式人生 > >6. C 語言 -- 運算子

6. C 語言 -- 運算子

本部落格主要內容為 “小甲魚” 視訊課程《帶你學C帶你飛》【第一季】 學習筆記,文章的主題內容均來自該課程,在這裡僅作學習交流。在文章中可能出現一些錯誤或者不準確的地方,如發現請積極指出,十分感謝。 也歡迎大家一起討論交流,如果你覺得這篇文章對你有所幫助,記得評論、點贊哦 ~(。・∀・)ノ゙

  C 語言通過提供大量的運算子來支援我們對資料進行處理,例如將一個值存放到變數中,使用的是賦值運算子(=);對字串中的某個字元進行索引,使用方括號([])作為下標運算子實現。本篇博文將主要介紹算術運算子關係運算符邏輯運算子這三種運算子。

1 . 算術運算子

  算術運算子就是做加減乘除運算的運算子了,常見的運算子有如下這些 在這裡插入圖片描述

其中有三點需要注意:   (1) 整數間的除法採用的是取整的方式,而不是四捨五入的方式,如 5/3 = 1   (2) 浮點數間的除法則能獲得一個相對逼近結果的值,如5.0/3.0 = 1.666667   (3) 求餘運算子要求 % 兩邊的運算元都要是整數,其結果也是整數。

1.1 什麼是 “目”

  在上面的表格中有的運算子是雙目運算子,有的運算子是單目運算子,那什麼是 “目” 呢?如下圖所示

其中的加號就是運算子,被運算子作用的運算物件稱之為運算元,比如 1 + 2,那麼 1 和 2 就是被加法運算子(+)作用的兩個運算元。我們說一個運算子是雙目運算子還是單目運算子,就是看它有多少個運算元。所以很明顯,除了正負號運算子,剩下的都是單目運算子。

1.2 表示式

  用運算子和括號將運算元連線起來的式子,我們稱之為表示式。比如說1+2'a' + 'b'1 + 2 + -1 - 9%5,這些都是表示式。

  對於較為複雜的表示式我們應該考慮運算子的優先順序和結合性,大部分的運算子和我們的認識一致,比如先乘除後加減,有括號的先算括號內的。但是也會有一些較為特殊的運算子需要我們注意下計算的順序,這裡我們給出一個參考,可以快速檢視運算子號的優先順序。順便在這裡我也安利下我常用的方法,很簡單!就是遇到不確定的優先順序直接用括號把想優先計算的括起來~

1.3 型別轉換

  當一個運算子的幾個運算元型別不同時,編譯器需要將它們轉換為共同的某種資料型別,才能進行運算。通常情況下,編譯器會將佔記憶體比較小的運算元,先轉換為與佔記憶體較大的運算元的相同型別,然後再進行運算。這樣做的目的就是為了確保計算的精確度。

  除了編譯器幫你自動轉換不同型別的運算元之外,C 語言還允許你強制轉換運算元的資料型別。做法就是在運算元的前邊用小括號將目標資料型別括起來。

1.4 舉例說明

  第一個程式是關於運算優先順序的示例

#include <stdio.h>
#include <math.h>

int main()
{
	int i, j, k;

	i = 1 + 2;
	j = 1 + 2 * 3;
	k = i + j + -1 + pow(2, 3); // 3 + 7 + (-1) + 8

	printf("i = %d\n", i);
	printf("j = %d\n", j);
	printf("k = %d\n", k);

	return 0;
}

實驗結果為

i = 3
j = 7
k = 17

其中需要注意的是 -1 中的負號優先順序很高,在 C 語言中排在第二優先順序而我們常用的乘除排在第三優先順序,加減排在第四優先順序。

  第二個程式是關於型別轉換的示例

#include <stdio.h>

int main()
{
        printf("整型輸出:%d\n", -5 / 2);
        printf("整型輸出:%d\n", 1 + 2.8);
        printf("整型輸出:%d\n", 1 + (int)2.8);
        printf("整型輸出:%d\n", (int)(1 +2.8));
        printf("浮點型輸出:%f\n", 1 + 2.0);

        return 0;
}

實驗結果如下圖所示 在這裡插入圖片描述   從輸出的第一行可以看到,整數的取整是向它的絕對值方向取整,-2.5 會取整為 -2,而 2.5 會取整為 2。

   gcc 對第二個 printf 中的內容進行了警告,大概意思是說我們將一個 double 型別的變數以 int 型進行列印輸出,可以看到輸出的結果明顯是不對的。

   如果想輸出 1 + 2.8 的整型形式的結果,可以先通過 (int) 2.8 強制將其轉變為整型再進行相加,也可以將相加的結果直接強制轉變為整型。

2. 關係運算符

  如下圖所示,可以使用關係運算符來比較兩個數的大小關係

其中同一個大括號中的關係運算符的優先順序相同,上面的優先順序要高於下面的優先順序。用關係運算符將兩邊的變數、資料或表示式連線起來,稱之為關係表示式,如下所示打印出每一個關係表示式的值

#include <stdio.h>

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

        printf("%d\n", 1 < 2);
        printf("%d\n", a > b);
        printf("%d\n", a <= 1 + b);
        printf("%d\n", 'a' + 'b' <= 'c');
        printf("%d\n", "ab" < "cd");
        printf("%d\n", (a=3) > (b=5));

        return 0;
}

當關系表示式成立的時候會返回數字 1 ,當關系表示式成立的時候會返回數字 0 。其中整型的變數和整型的常量之間進行關係運算是很好理解的,但是字元型變數是如何進行比較的呢?很簡單通過字元型變數所對應的 ASCII 碼。

  但是倒數第二個中的字串是如何比較大小的呢?符串比較就是從兩個字串第一個位置開始比較對應位置上的字元的ASCII碼值,直到分出大小或者達到某個字串的結尾,先到達結尾的字串小。例如: “AC”<“B” 因為A的ASCII碼值比B小,那麼後面的就不在比較了 “ACA”<“ACAX” 前面三個"ACA"都相同,最後一個前面的字串已到末尾,所以小。[3]^{[3]}

  因此實驗結果如下所示

1
1
0
0
1
0

3. 邏輯運算子

  C語言總共提供了三種邏輯運算子,如下圖所示 在這裡插入圖片描述 首先要注意它們之間的優先順序,因為邏輯非是一種單目運算子,而剩下的兩種是雙目運算子,多以邏輯非的優先順序最高。用邏輯運算子將兩邊的變數、資料或表示式連線起來,稱之為邏輯表示式,如下為打印出每一個關係表示式的值

#include <stdio.h>

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

	printf("%d\n", 3 > 1 && 1 < 2);
	printf("%d\n", 3 + 1 || 2 == 0);
	printf("%d\n", !(a + b));
	printf("%d\n", !0 + 1 < 1 || !(3 + 4));
	printf("%d\n", 'a' - 'b' && 'c');

	return 0;
}

  通過之前文章我們知道關係運算符的優先順序要高於邏輯運算子,所以第一個 printf 中的內容顯然為真;在第二個 printf|| 左側的是 3+1 ,實際上在 C 語言中任意非零數字都可以算作是真,所以該語句名明顯應該輸出 1 ;剩下的幾個例子很好理解可以自行推導一下。

  上面的程式碼執行的結果如下所示

1
1
0
0
1

3.1 短路求值

  短路求值又稱最小化求值,是一種邏輯運算子的求值策略。只有當第一個運算數的值無法確定邏輯運算的結果時,才對第二個運算數進行求值。C語言對於邏輯與和邏輯或採用短路求值的方式。

  所以在上面給講述的字串的比較方法就是遵從了這個原則。另一方面,比如說在 3 > 1 && 1 < 2 只根據前半部分是沒有辦法判斷該表示式的取值的,所以還有根據後面的運算數求值;但是對於 3 == 1 && 1 < 2 來講,根據第一個運算數字就可以判斷該邏輯表示式為假,所以後面的比較運算就不會發生。

  又比如下面這個例子

#include <stdio.h>

int main()
{
	int a = 3, b = 3;

	(a = 0) && (b = 5);
	printf("a = %d, b = %d\n", a, b);

	(a = 1) || (b = 5);
	printf("a = %d, b = %d\n", a, b);

	return 0;
}

它的執行結果為

a = 0, b = 3
a = 1, b = 3

這是因為執行到 a=0 的時候已經可以得到 (a = 0) && (b = 5); 所以後面的 b = 5 就不會被執行因此輸出 a = 0, b = 3;下面的同樣當執行到 a = 1 就已經的到了 (a = 1) || (b = 5) 的值,所以仍然不會執行 b = 5 ,列印輸出 a = 1, b = 3 。所以在採用邏輯運算表示式的時候一定要考慮清楚在邏輯運算子的左右應該分別放什麼。

參考

歡迎大家關注我的知乎號(左側)和經常投稿的微信公眾號(右側) 在這裡插入圖片描述