C語言 -- 操作符詳解?
- 1. 操作符的分類
- 2. 二進制和進制轉換?
- 2.1 2進制轉10進制?
- 2.1.1 10進制轉2進制數字?
- 2.2 2進制轉8進制和16進制?
- 2.2.1 2進制轉8進制?
- 2.2.2 2進制轉16進制?
- 3. 原碼、反碼、補碼?
- 4. 移位操作符?
- 4.1 左移操作符?
- 4.2 右移操作符?
- 5. 位操作符:&、|、^、~?
- 6. 單目操作符
- 7. 逗號表達式?
- 8. 下標訪問[]、函數調用()?
- 8.1 [ ] 下標引用操作符?
- 8.2 函數調用操作符 ?
- 9. 結構成員訪問操作符?
- 9.1 結構體?
- 9.1.1 結構的聲明?
- 9.1.2 結構體變量的定義和初始化?
- 9.2 結構成員訪問操作符?
- 9.2.1 結構體成員的直接訪問
- 9.2.2 結構體成員的間接訪問
1. 操作符的分類
? 算術操作符: + 、- 、* 、/ 、%
? 移位操作符: << >> ?
? 位操作符: & | ^ `?
? 賦值操作符: = 、+= 、 -= 、 * = 、 /= 、%= 、<<= 、>>= 、&= 、|= 、^= ?
? 單目操作符: !、++、–、&、*、+、-、~ 、sizeof、(類型)
? 關系操作符: > 、>= 、< 、<= 、 == 、 != ?
? 邏輯操作符: && 、||
? 條件操作符: ? :
? 逗號表達式: ,
? 下標引用: []
? 函數調用: ()
? 結構成員訪問: . 、->
上述的操作符,我們已經講過算術操作符、賦值操作符、邏輯操作符、條件操作符和部分的單目操作符,今天繼續介紹一部分,操作符中有一些操作符和二進制有關系,我們先鋪墊一下二進制的和進制轉換的知識。
2. 二進制和進制轉換?
其實我們經常能聽到2進制、8進制、10進制、16進制這樣的講法,那是什么意思呢?其實2進制、8進制、10進制、16進制是數值的不同表示形式而已。?
比如:數值15的各種進制的表示形式:?
我們重點介紹一下二進制:
首先我們還是得從10進制講起,其實10進制是我們生活中經常使用的,我們已經形成了很多嘗試:?
? 10進制中滿10進1?
? 10進制的數字每一位都是0~9的數字組成?
其實二進制也是一樣的
? 2進制中滿2進1?
? 2進制的數字每一位都是0~1的數字組成?
那么 1101 就是二進制的數字了。
2.1 2進制轉10進制?
其實10進制的123表示的值是一百二十三,為什么是這個值呢?其實10進制的每一位是權重的,10進制的數字從右向左是個位、十位、百位…,分別每一位的權重是?10的零次方 , 10的一次方 , 10的二次方 … ?
如下圖:
2進制和10進制是類似的,如果是2進制的1101,該怎么理解呢??
如下圖:
2.1.1 10進制轉2進制數字?
2.2 2進制轉8進制和16進制?
我們需要先了解一下:
2.2.1 2進制轉8進制?
進制的數字每一位是0 ~ 7的,0 ~ 7的數字,各自寫成2進制,最多有3個2進制位就足夠了,比如7的二進制是111,所以在2進制轉8進制數的時候,從2進制序列中右邊低位開始向左每3個2進制位會換算一個8進制位,剩余不夠3個2進制位的直接換算。?
下面是一個八進制的數字就%d打印出來:
2.2.2 2進制轉16進制?
16進制的數字每一位是0 ~ 9,a ~ f 的,0~9,a ~ f的數字,各自寫成2進制,最多有4個2進制位就足夠了,比如 f 的二進制是1111,所以在2進制轉16進制數的時候,從2進制序列中右邊低位開始向左每4個2進制位會換算一個16進制位,剩余不夠4個二進制位的直接換算。?
3. 原碼、反碼、補碼?
- 整數的2進制表示方法有三種,即原碼、反碼和補碼?
- 有符號整數的三種表示方法均有符號位和數值位兩部分,2進制序列中,最高位的1位是被當做符號位,剩余的都是數值位。
- 符號位都是用0表示“正”,用1表示“負”。?
- 正整數的原、反、補碼都相同。
- 負整數的三種表示方法各不相同。
原碼:直接將數值按照正負數的形式翻譯成二進制得到的就是原碼。
反碼:將原碼的符號位不變,其他位依次按位取反就可以得到反碼。
補碼:反碼+1就得到補碼。?
反碼得到原碼也是可以使用:取反,+1的操作。?
例子1:
例子2:
對于整形來說:數據存放內存中其實存放的是補碼。
為什么呢?
下面舉個例子:
注意:
4. 移位操作符?
4.1 左移操作符?
移位規則:左邊拋棄、右邊補0?
例子如下:
圖示:
4.2 右移操作符?
移位規則:首先右移運算分兩種:
例子如下:
以%d形式打印的是原碼
圖示:邏輯右移演示
算數右移演示:
注:右移到底是算數右移還是邏輯右移取決于編譯器的實現,大部分的編譯器上是算數右移,在VS2022上采用的算數右移。
警告??:對于移位運算符,不要移動負數位,這個是標準未定義的。
例如:
5. 位操作符:&、|、^、~?
位操作符有:
&------ >按位與?
| -------->按位或
^ ------->按位異或?
~ ------>按位取反
注:他們的操作數必須是整數,操作的都是二進制位。
按位與計算規則:
對應的二進制位進行與運算,只要有0就是0,兩個同時為1才是1
例子:
按位或計算規則
對應的二進制位進行或運算,只要有1就是1,兩個同時為0才是0
例子:
按位異或計算規則
對應的二進制位進行異或運算,相同為0,相異為1
例子:
按位取反 ~
例子:
一道變態的面試題:
不能創建臨時變量(第三個變量),實現兩個數的交換。
異或操作符的特點:
a^a = 0
0^a = a
練習1:編寫代碼實現:求一個整數存儲在內存中的二進制中1的個數。?
方法一:
方法二:
方法三:
首先的先明白一個知識:
// n = n & (n - 1)
效果:把n的二進制中最右邊的1去掉了
//n=15
//1111 - n
//1110 - n-1
//1110 - n
//1101 - n-1
//1100 - n
//1011 - n-1
//1000 - n
//0111 - n-1
//0000 - n
代碼例子:
練習2:判斷一個數n是否是2的次方數
特點:
//000001
//000010
//000100
//001000
//…
代碼:
練習2:二進制位置0或者置1?
編寫代碼將13二進制序列的第5位修改為1,然后再改回0?
6. 單目操作符
7. 逗號表達式?
逗號表達式,就是用逗號隔開的多個表達式。
逗號表達式,從左向右依次執行。整個表達式的結果是最后一個表達式的結果。
例子:
8. 下標訪問[]、函數調用()?
8.1 [ ] 下標引用操作符?
操作數:一個數組名 + 一個索引值 ?
8.2 函數調用操作符 ?
接受一個或者多個操作數:第一個操作數是函數名,剩余的操作數就是傳遞給函數的參數。
例子:
注意:sizeof是操作符,不是函數
9. 結構成員訪問操作符?
9.1 結構體?
C語言已經提供了內置類型,如:char、short、int、long、float、double等,但是只有這些內置類型還是不夠的,假設我想描述學生,描述一本書,這時單一的內置類型是不行的。描述一個學生需要名字、年齡、學號、身高、體重等;描述一本書需要作者、出版社、定價等。C語言為了解決這個問題,增加了結構體這種自定義的數據類型,讓程序員可以自己創造適合的類型。
9.1.1 結構的聲明?
聲明結構體類型的時候,再創建一個變量
struct tag
{
member-list; //成員列表,一個或多個成員
}variable-list;
- struct 是結構體類型的關鍵字
- tag 結構體名稱/標簽
- struct tag 是用戶定義的結構體類型
- member-list 結構體成員名
- variable-list 是定義的結構體類型變量
描述一個學生
9.1.2 結構體變量的定義和初始化?
1.變量的定義
2.結構體對象初始化
3.結構體嵌套結構體
9.2 結構成員訪問操作符?
9.2.1 結構體成員的直接訪問
結構體成員的直接訪問是通過點操作符(.)訪問的。點操作符接受兩個操作數
使用方式:結構體變量.成員名
如下所示:
例子1:?
例子2:
9.2.2 結構體成員的間接訪問
有時候我們得到的不是一個結構體變量,而是得到了一個指向結構體的指針。
使用方式:結構體指針->成員名?
如下所示: