c語言 基本運算
計算機的基本能力就是計算,所以一門程式設計語言的計算能力是非常重要的。C語言之所以無所不能,是因為它不僅有豐富的資料型別,還有強大的計算能力。C語言一共有34種運算子,包括了常見的加減乘除運算。這講就對C語言中的運算子做一個詳細介紹。
一:算術運算子算術運算子非常地簡單,就是小學數學裡面的一些加減乘除操作。不過呢,還是有一些語法細節需要注意的。
1.加法運算子 +
1 int a = 10; 2 3 int b = a + 5;
在第3行利用加法運算子 + 進行了加法運算,再將和賦值給了變數b,最終變數b的值是15
2.減法運算子 或 負值運算子 -
1 int b = 10 - 5; 2 3 int a = -10;
1> 在第1行利用減法運算子 - 進行了減法運算,再將差賦值給了變數b,最終變數b的值是5
2> 在第3行中,這個 - 並不是什麼減法運算子,而算是一個負值運算子,-10代表的是負十
3.乘法運算子 *
1 int b = 10 * 5;
注意:乘法運算子並不是x或者X,而是星號*。變數b最終的值是50。
4.除法運算子 /
1 double a = 10.0 / 4; 2 double b = 10 / 4; 3 4 printf("a=%f, b=%f \n", a, b);
注意:除法運算子並不是÷,而是一個正斜槓 /
1> 第1行中的10.0是浮點型,4是整型,因此會將4自動型別提升為浮點型後再進行運算,最後變數b的值是2.5
2> 第2行中的10和4都是整型,計算機中的運算有個原則:相同資料型別的值才能進行運算,而且運算結果依然是同一種資料型別。因此,整數除於整數,求出來的結果依然是整數,會損失小數部分。最後變數b的值是2。檢視輸出結果:
3> 如果想讓 整數除於整數 不損失精度的話,可以將某個整數強制轉換為浮點型資料
1 double a = (double)10 / 4; 2 3 double b = 10 / (double)4; 4 5 double c = (double)10 / (double)4; 6 7 double d = (double) (10 / 4);
- 10和4之間只要有1個強轉為浮點型資料即可,另外1個整數會自動型別提升為浮點型資料。因此,變數a、b、c的值都是2.5。
- 變數d的情況就不一樣了,第7行程式碼的意思是先計算(10/4)的值,再將(10/4)的值強轉為浮點型資料。(10/4)的值是2,將2強轉為浮點型資料,那不也就是2麼?所以,變數d的值是2
5.模運算子 或稱 取餘運算子 %
注意:這個%並不是除號÷,它是一個取餘運算子,或者叫做模運算子。取餘的意思是,取得兩個整數相除之後的餘數。比如,5除於2的餘數是1,5除於3的餘數是2。因此使用這個%有個原則:%兩側必須都為整數。下面的寫法是錯誤的:
1 int a = 5.0 % 2;
編譯器會直接報錯,因為5.0並非整數。
1> 正數取餘
1 int a = 5 % 2; 2 int b = 2 % 5;
簡單計算可得:變數a的值為1,變數b的值為2
2> 負數取餘
1 int a = -5 % 2; 2 int b = 5 % -2; 3 int c = -5 % -2;
利用%求出來的餘數是正數還是負數,由%左邊的被除數決定,被除數是正數,餘數就是正數,反之則反。因此變數a、b、c的值分別是-1、1、-1
6.運算順序
1> 算術表示式
用算術運算子將資料連線起來的式子,稱為“算術表示式”。比如a + b、10 * 5等。如果表示式比較複雜的話,那麼就要注意一下它的運算順序。表示式的運算順序是按照運算子的結合方向和優先順序進行的。
2> 結合方向
算術運算子的結合方向是從左到右。例如表示式2+3+4,先計算2+3。
3> 優先順序
優先順序越高,就越先進行運算,當優先順序相同時,參照結合方向。下面是算術運算子的優先順序排序:
負值運算子(-) > 乘(*)、除(/)、模(%)運算子 > 加(+)、減(-)運算子
例如表示式4+5*8/-2的計算順序為:-、*、/、+,最後的結果是-16
4> 小括號
如果需要先計算優先順序低的可以使用小括號()括住,小括號的優先順序是最高的!
- 例如4+5*8-2預設的計算順序是:*、+、-
- 如果想先執行加法運算,就可以這樣寫:(4+5)*8-2,最後的結果都是不一樣的
二、賦值運算子
賦值運算子又分兩種:簡單賦值運算子 和 複合賦值運算子。
1.簡單賦值運算子 =
1> 簡單用法
其實這個等號 = 從講變數開始就見過它了,它的作用是將右邊的值賦值給左邊。
1 int a = 10 + 5;
賦值運算子的結合方向是:從右到左,而且優先順序比算術運算子低。因此先進行等號=右邊的加法運算,運算完畢後再將結果賦值給等號右邊的變數。最後變數a的值是15。
2> 連續賦值
1 int a, b; 2 3 a = b = 10;
- 在第1行分別定義了int型別的變數a、b
- 第3行程式碼的意思:將10賦值給變數b,再把變數b的值賦值給a。所以最後變數a、b的值都是10
3> 使用注意
等號=左邊只能是變數,不能是常量!常量都是不可變的,怎麼可以再次賦值呢?下面的寫法是錯誤的:
1 10 = 10 + 5;
2.複合賦值運算子
- += 加賦值運算子。如a += 3+2,等價於 a = a +(3+2)
- -= 減賦值運算子。如a -= 3+2,等價於 a = a -(3+2)
- *= 乘賦值運算子。如a *= 3+2,等價於 a = a *(3+2)
- /= 除賦值運算子。如a /= 3+2,等價於 a = a /(3+2)
- %= 取餘賦值運算子。如a %= 3+2,等價於 a = a %(3+2)
三、自增運算子和自減運算子
1.簡介
- ++ 自增運算子。如a++,++a,都等價於a = a+1
- -- 自減運算子。如a--,--a,都等價於a = a-1
注意:你寫個5++是錯誤的,因為5是常量。
2.++a和a++的區別
1> 單獨使用++a和a++時,它們是沒區別的
1 int a = 10; 2 a++;
1 int a = 10; 2 ++a;
上面兩段程式碼的效果都是讓a的值+1,最後a的值都為11
2> 下面這種情況,++a和a++就有區別了
1 int a = 10; 2 3 int b = ++a;
1 int a = 10; 2 3 int b = a++;
上面兩段程式碼的執行結果是有區別的。
- 第1段程式碼:++a的意思是先對a執行+1操作,再將a的值賦值給b。因此最後a、b的值都是11
- 第2段程式碼:a++的意思是先將a的值拷貝出來一份,然後對a執行+1操作,於是a變成了11,但是拷貝出來的值還是10,a++運算完畢後,再將拷貝出來的值10賦值給了b,所以最後變數b的值是10,變數a的值是11
--a和a--的區別也是一樣的。
3> 再來看一個比較刁鑽的例子
1 int a = 10; 2 3 a = a++;
很多人一眼看上去,覺得最後a的值應該是11,其實最後a的值是10。前面已經說過a++的作用了,這裡也是一樣的。先將a的值拷貝出來一份,然後對a執行+1操作,於是a變成了11,但是拷貝出來的值還是10,a++運算完畢後,再將拷貝出來的值10賦值給了a,所以最後變數a的值是10
四、sizeof
* sizeof可以用來計算一個變數或者一個常量、一種資料型別所佔的記憶體位元組數。
int size = sizeof(10); printf("10所佔的位元組數:%d", size);
輸出結果:,10是int型別的資料,在64bit編譯器環境下,int型別需要佔用4個位元組
* sizeof一共有3種形式
- sizeof( 變數\常量 )
sizeof(10); char c = 'a'; sizeof(c);
- sizeof 變數\常量
sizeof 10; char c = 'a'; sizeof c;
- sizeof( 資料型別 )
sizeof(float);
注意,不可以寫成sizeof float;
五、逗號運算子
* 逗號運算子主要用於連線表示式,例如:
1 int a = 9; 2 int b = 10; 3 4 a = a+1 , b = 3*4;
* 用逗號運算子連線起來的表示式稱為逗號表示式,它的一般形式為:
表示式1, 表示式2, … …, 表示式n
逗號表示式的運算過程是:從左到右的順序,先計算表示式1,接著計算表示式2,...,最後計算表示式n
* 逗號運算子也是一種運算子,因此它也有運算結果。整個逗號表示式的值是最後一個表示式的值
1 int a = 2; 2 int b = 0; 3 int c; 4 5 c = (++a, a *= 2, b = a * 5); 6 7 printf("c = %d", c);
++a的結果為3,a *= 2的結果為6,b = a * 5的結果為30。因此,輸出結果為:
這裡要注意的是,右邊的表示式是有用括號()包住的,如果不用括號包住,也就是:
1 c = ++a, a *= 2, b = a * 5; 2 printf("c = %d", c);
輸出結果將為:,因為c = ++a也屬於逗號表示式的一部分,跟後面的a *= 2以及b = a * 5是相互獨立的
六、關係運算符
1.“真”與“假”
1> 預設情況下,我們在程式中寫的每一句正確程式碼都會被執行。但很多時候,我們想在某個條件成立的情況下才執行某一段程式碼。比如微信的這個介面:
如果使用者點選了註冊按鈕,我們就執行“跳轉到註冊介面”的程式碼;如果使用者點選了登入按鈕,我們就執行“跳轉到登入介面”的程式碼。如果使用者沒做出任何操作,就不執行前面所說的兩段程式碼。像這種情況的話可以使用條件語句來完成,但是我們暫時不學習條件語句,先來看一些更基礎的知識:如何判斷一個條件成不成立。如果這個都不會判斷,還執行什麼程式碼。
2> 在C語言中,條件成立稱為“真”,條件不成立稱為“假”,因此,判斷條件是否成立,就是判斷條件的“真假”。那怎麼判斷真假呢?C語言規定,任何非0值都為“真”,只有0才為“假”。也就是說,108、-18、4.5、-10.5等都是“真”,0則是“假”。
2.關係運算符的簡單使用
C語言中還提供了一些關係運算符,可以用來比較兩個數值的大小。
- < 小於。比如a<5
- <= 小於等於。比如a<=5
- > 大於。比如a>5
- >= 大於等於。比如a>=5
- == 等於。比如a==5
- != 不等於。比如a!=5
關係運算符的運算結果只有2種:如果條件成立,結果就為1,也就是“真”;如果條件不成立,結果就為0,也就是“假”。
1 int a1 = 5 > 4; // 1 2 3 int a2 = 5 < 4; // 0
3.關係運算符的使用注意
1> 關係運算符中==、!=的優先順序相等,<、<=、>、>=的優先順序相等,且前者的優先順序低於後者
例如2==3>1 :先算3>1,條件成立,結果為1。再計算2==1,條件不成立,結果為0。因此2==3>1的結果為0。
2> 關係運算符的結合方向為“從左往右”
例如4>3>2 :先算4>3,條件成立,結果為1。再與2比較,即1>2,條件不成立,結果為0。因此4>3>2的結果為0。
3> 關係運算符的優先順序小於算術運算子
例如3+4>8-2 :先計算3+4,結果為7。再計算8-2,結果為6。最後計算7>6,條件成立,結果為1。因此3+4>8-2的結果為1。
七、邏輯運算子
有時候,我們需要在多個條件同時成立的時候才能執行某段程式碼,比如:使用者只有同時輸入了QQ和密碼,才能執行登入程式碼,如果只輸入了QQ或者只輸入了密碼,就不能執行登入程式碼。這種情況下,我們就要藉助於C語言提供的邏輯運算子。
C語言提供了3個邏輯運算子:&&(邏輯與)、||(邏輯或)、!(邏輯非)。注意:這些都是英文字元,不要寫成中文字元。跟關係運算符一樣,邏輯運算的結果只有2個:“真”為1,“假”為0
1.&& 邏輯與
1> 使用格式
“條件A && 條件B”
2> 運算結果
只有當條件A和條件B都成立時,結果才為1,也就是“真”;其餘情況的結果都為0,也就是“假”。因此,條件A或條件B只要有一個不成立,結果都為0,也就是“假”
3> 運算過程
- 總是先判斷條件A是否成立
- 如果條件A成立,接著再判斷條件B是否成立:如果條件B成立,“條件A && 條件B”的結果就為1,即“真”,如果條件B不成立,結果就為0,即“假”
- 如果條件A不成立,就不會再去判斷條件B是否成立:因為條件A已經不成立了,不管條件B如何,“條件A && 條件B”的結果肯定是0,也就是“假”
4> 舉例
邏輯與的結合方向是“自左至右”。比如表示式 (a>3) && (a<5)
- 若a的值是4:先判斷a>3,成立;再判斷a<5,也成立。因此結果為1
- 若a的值是2:先判斷a>3,不成立,停止判斷。因此結果為0
- 因此,如果a的值在(3, 5)這個範圍內,結果就為1;否則,結果就為0
5> 注意
- 若想判斷a的值是否在(3, 5)範圍內,千萬不能寫成3<a<5,因為關係運算符的結合方向為“從左往右”。比如a為2,它會先算3<a,也就是3<2,條件不成立,結果為0。再與5比較,即0<5,條件成立,結果為1。因此3<a<5的結果為1,條件成立,也就是說當a的值為2時,a的值是在(3, 5)範圍內的。這明顯是不對的。正確的判斷方法是:(a>3) && (a<5)
- C語言規定:任何非0值都為“真”,只有0才為“假”。因此邏輯與也適用於數值。比如 5 && 4的結果是1,為“真”;-6 && 0的結果是0,為“假”
2.|| 邏輯或
1> 使用格式
“條件A || 條件B”
2> 運算結果
當條件A或條件B只要有一個成立時(也包括條件A和條件B都成立),結果就為1,也就是“真”;只有當條件A和條件B都不成立時,結果才為0,也就是“假”。
3> 運算過程
- 總是先判斷條件A是否成立
- 如果條件A成立,就不會再去判斷條件B是否成立:因為條件A已經成立了,不管條件B如何,“條件A || 條件B”的結果肯定是1,也就是“真”
- 如果條件A不成立,接著再判斷條件B是否成立:如果條件B成立,“條件A || 條件B”的結果就為1,即“真”,如果條件B不成立,結果就為0,即“假”
4> 舉例
邏輯或的結合方向是“自左至右”。比如表示式 (a<3) || (a>5)
- 若a的值是4:先判斷a<3,不成立;再判斷a>5,也不成立。因此結果為0
- 若a的值是2:先判斷a<3,成立,停止判斷。因此結果為1
- 因此,如果a的值在(-∞, 3)或者(5, +∞)範圍內,結果就為1;否則,結果就為0
5> 注意
C語言規定:任何非0值都為“真”,只有0才為“假”。因此邏輯或也適用於數值。比如 5 || 4的結果是1,為“真”;-6 || 0的結果是1,為“真”;0 || 0的結果是0,為“假”
3.! 邏輯非
1> 使用格式
“! 條件A”
2> 運算結果
其實就是對條件A進行取反:若條件A成立,結果就為0,即“假”;若條件A不成立,結果就為1,即“真”。也就是說:真的變假,假的變真。
3> 舉例
邏輯非的結合方向是“自右至左”。比如表示式 ! (a>5)
- 若a的值是6:先判斷a>5,成立,再取反之後的結果為0
- 若a的值是2:先判斷a>3,不成立,再取反之後的結果為1
- 因此,如果a的值大於5,結果就為0;否則,結果就為1
4> 注意
- 可以多次連續使用邏輯非運算子:!(4>2)結果為0,是“假”,!!(4>2)結果為1,是“真”,!!!(4>2)結果為0,是“假”
- C語言規定:任何非0值都為“真”,只有0才為“假”。因此,對非0值進行邏輯非!運算的結果都是0,對0值進行邏輯非!運算的結果為1。!5、!6.7、!-9的結果都為0,!0的結果為1
4.優先順序
邏輯運算子的優先順序順序為: 小括號() > 負號 - > ! > 算術運算子 > 關係運算符 > && > ||
- 表示式!(3>5) || (2<4) && (6<1) :先計算 !(3>5)、(2<4)、(6<1),結果為1,式子變為1 || 1 && 0,再計算1 && 0,式子變為1 || 0,最後的結果為1
- 表示式3+2<5||6>3 等價於 ((3+2) < 5) || (6>3),結果為1
- 表示式4>3 && !-5>2 等價於 (4>3) && ((!(-5)) > 2) ,結果為0
八、三目運算子
1.N目運算子
- 像邏輯非(!)、負號(-)這種只連線一個數據的符號,稱為“單目運算子”,比如!5、-5。
- 像算術運算子、關係運算符、邏輯運算子這種連線二個數據的負號,稱為“雙目運算子”,比如6+7、8*5、5>6、4 && 0、
- 以此類推,連線3個數據的運算子,應該稱為“三目運算子”
2.三目運算子
C語言提供了唯一一個三目運算子:條件運算子。
1> 使用格式
表示式A ? 表示式B : 表示式C
2> 運算結果
如果表示式A成立,也就是為“真”,條件運算子的結果就是表示式B的值,否則,就為表示式C的值
3> 結合方向和優先順序
- 優先順序順序為:算術運算子 > 關係運算符 > 條件運算子 > 賦值運算子
- 條件運算子的結合方向是“從右至左”
1 int a = 3>4 ? 4+5 : 5>4 ? 5+6 : 6>7+1;
上面的程式碼等價於
1 int a = (3>4) ? (4+5) : ( (5>4) ? (5+6) : (6>(7+1)) );
簡化一下就是
1 int a = 0 ? 9 : ( 1 ? 11 : 0 );
繼續簡化為
1 int a = 0 ? 9 : 11;
所以a的值是11
九、位運算子
所謂位運算就是對每一個二進位制位進行運算。C語言一共提供了6種位運算子,只能對整數進行操作,分別是:&按位與、|按位或、^按位異或、<<左移、>>右移、~取反。
1.& 按位與
1> 使用形式:整數a & 整數b
2> 功能:整數a和b各對應的二進位相與。只有對應的兩個二進位均為1時,結果位才為1,否則為0。參與運算的數以補碼方式出現。
3> 舉例:比如9&5,其實就是1001&101=1,因此9&5=1
4> 規律:
- 相同整數相&的結果是整數本身。比如5&5=5
- 多個整數相&的結果跟順序無關。比如5&6&7=5&7&6
2.| 按位或
1> 使用形式:整數a | 整數b
2> 功能:整數a和b各對應的二進位相或。只要對應的二個二進位有一個為1時,結果位就為1,否則為0。參與運算的數以補碼方式出現。
3> 舉例:比如9|5,其實就是1001|101=1101,因此9|5=13
4> 規律:
- 相同整數相|的結果是整數本身。比如5|5=5
- 多個整數相|的結果跟順序無關。比如5|6|7=5|7|6
3.^ 按位異或
1> 使用形式:整數a ^ 整數b
2> 功能:整數a和b各對應的二進位相異或。當對應的二進位相異(不相同)時,結果為1,否則為0。參與運算的數以補碼方式出現。
3> 舉例:比如9^5,其實就是1001^101=1100,因此9^5=12
4> 規律:
- 二進位制中,與1相^就會取反,與0相^保持原位
- 相同整數相^的結果是0。比如5^5=0
- 多個整數相^的結果跟順序無關。比如5^6^7=5^7^6
- 因此得出結論:a^b^a = b
4.~ 取反
1> ~為單目運算子,具有右結合性,使用形式:~整數a
2> 功能:對整數a的各二進位進行取反(0變1,1變0)
3> 舉例:比如~9,其實就是~(0000 0000 0000 0000 0000 0000 0000 1001)=(1111 1111 1111 1111 1111 1111 1111 0110),因此~9=-10
5.<< 左移
1> <<是雙目運算子,使用形式:整數a<<正數n
2> 功能:把整數a的各二進位全部左移n位,高位丟棄,低位補0。左移n位其實就是乘以2的n次方。
3> 舉例:3<<4,3本來是0000 0011,左移4位後變成了0011 0000,因此3<<4 = 48 = 3 * 24
4> 需要注意的是:由於左移是丟棄最高位,0補最低位,所以符號位也會被丟棄,左移出來的結果值可能會改變正負性
6.>> 右移
1> >>是雙目運算子,使用形式:整數a>>正數n
2> 功能:把整數a的各二進位全部右移n位,保持符號位不變。右移n位其實就是除以2的n次方。
3> 舉例:32>>3,32本來是0010 0000,右移3位後變成了0000 0100,因此32>>3 = 4 = 32 / 23