当前位置:网站首页>【C語言】符號的深度理解
【C語言】符號的深度理解
2022-07-04 21:25:00 【程序猿教你打籃球】
You wangt somenthing, go get it!
目錄
1、按比特運算符
1.1 按比特或 ( | ) 和 按比特與 ( & )
上期我們講到過邏輯或和邏輯與,他們得到的結果是真假值,但我們一定要區分清楚,按比特運算符 "|" 和 "&" 與邏輯運算符 "||" "&&" 是完全兩個概念。
按比特,簡明之意,按數值二進制比特來進行運算,都是在數據補碼的基礎上進行。
按比特或 "|" : 兩個數值的二進制補碼對應比特進行運算,對應比特有 1 則為 1 ,否則為 0。
按比特與 "&":兩個數值的二進制補碼對應比特進行運算,對應比特都為 1 則為 1, 否則為 0。
這裏我們舉例說明:
1 | 2 :
1 的二進制補碼:0000 0000 ... 0000 0001
2 的二進制補碼:0000 0000 ... 0000 0010
------按比特或結果: 0000 0000 ... 0000 0011 -> 對應十進制:3
1 & 2:
1 的二進制補碼:0000 0000 ... 0000 0001
2 的二進制補碼:0000 0000 ... 0000 0010
------按比特與結果: 0000 0000 ... 0000 0000 -> 對應十進制:0
其實有很多大學老師或者是書上都有可能把按比特或,按比特與,以及後面我們要講的按比特异或,他們會把每比特二進制運算後的結果稱為真或者假,其實這樣的說法是不够嚴謹的,真假是邏輯判斷,而按比特運算得到的結果是數值,而且在C語言中0錶示假,非0為真,所以我是不推薦這種說法。
1.2 按比特异或 ( ^ )
按比特或 "^" : 兩個數值的二進制補碼對應比特進行運算,相同為 0 , 不同為 1。
這裏我們舉例說明:
1 ^ 3 :
1 的二進制補碼:0000 0000 ... 0000 0001
3 的二進制補碼:0000 0000 ... 0000 0011
---按比特异或結果: 0000 0000 ... 0000 0010 -> 對應十進制:2
5 ^ 0 :
5 的二進制補碼:0000 0000 ... 0000 0101
0 的二進制補碼:0000 0000 ... 0000 0000
---按比特异或結果: 0000 0000 ... 0000 0101 -> 對應十進制:5
結論:任何數异或0都等於它本身
這裏有一道筆試題:不創建臨時變量,實現兩個數的交換。
//很多小夥伴直接想出來的做法:
int main()
{
int a = 10;
int b = 20;
printf("a = %d, b = %d\n", a, b);
a = a + b;
b = a - b;
a = a - b;
printf("a = %d, b = %d\n", a, b);
return 0;
}
但是我們仔細研究下這段代碼,他有沒有什麼隱藏的問題呢?
一個整型,占四個字節,也就是 32 個比特比特,這裏進行加法運算,就會產生進比特,萬一我們是兩個很大的數相加呢?他們的和超過了整型最大存儲範圍,那麼在計算機裏面就會發生截斷!為了避免發生這種現象,我們可以采取异或的方法來實現這道題:
最後還有一個很簡單的按比特取反操作符:~
用途:對一個數的二進制按比特取反(包括它的符號比特)
注意:以上的比特運算符, 他們的操作數必須是整數!
1.3 一個關於整型提昇的問題
有這樣一串代碼,問:為什麼一個char類型大小可以求出來是4字節?
無論任何比特運算符,都是要計算機進行計算的,而計算機中CPU具有運算能力,但計算的數據都是放在內存中的。所以,做任何運算,都必須將數據從內存拿到CPU的寄存器中。而寄存器默認的操作數寬度是32比特,可是,char類型數據只有1個字節,也就是8比特,不滿足32比特怎麼辦,這就需要整型提昇了!(詳細整型提昇大家可以查閱資料哦)
如果是一個有符號數的話:高比特補符號比特
如果是一個無符號數的話:高比特補0
2、移比特操作符
2.1 左移<< 右移>>操作符
<< 左移運算符是一個雙目運算符,功能是把左邊的運算數的各個二進制比特向左移動指定比特數。
>> 右移運算符是一個雙目運算符,功能是把右邊的運算數的各個二進制比特向右移動指定比特數。
注意:
<< 左移:最低比特丟弃,最高比特補零
>> 右移:
- 無符號數:最低比特丟弃,最高比特補零 [邏輯右移]
- 有符號數:最低比特丟弃,最高比特補符號比特 [算數右移]
以上在補碼中進行運算
警告:移比特運算符,請不要移動負數比特,這是標准未定義的!
左移我們好說,主要是右移我們需要細講一下:
明顯看到,這是在無符號數下進行右移,第一個小夥伴都不會感到驚訝, 可是第二個就有點不理解了,我們來解釋下:
這裏有一個問題,當 -1 准備放入變量 b 的時候我們需要看-1的類型嗎?
答案是不需要!內存中放的都是二進制補碼,本質上是把 -1 的補碼放入變量 b 當中,第二,右移操作符屬於計算,需要在CPU中進行,所以需要先把內存中 -1 的補碼拿到CPU寄存器中運算,按照我們的規則,右移中,無符號數低比特丟弃高比特補零,所以 -1 右移完成之後就變成了 0111 1111 ... 1111 1111,接著我們以 %d 有符號整型打印,就會把他當作有符號數看待,最高比特是 0 所以被認為是正數,轉化成十進制也就是如上打印的值。
第二個我們來看下有符號數右移:
這個相信大家就很好理解了,第一個高比特補符號比特也就是補 0,低比特丟弃,所以結果是 0,第二個高比特補符號比特也就是補 1,低比特丟弃,值仍然不變,還是 -1。
注意:a>>1 並不會改變 a 變量的值,就好比如 a + 1。這樣寫才會改變:a = a >> 1;
2.2 習題練習
學完了上期的邏輯操作符,和本期的移比特操作符,我們來練練手:
請你設計一個宏可以指定數據第幾個比特比特更改為 1 ,並設計一個函數將各個比特比特打印出來。
//參考
#define SETBIT(a, num) ((a) |= (1 << (num - 1)) )
void PrintBit(int a)
{
int num = 31;
while (num >= 0)
{
if ((a & (1 << num)))
printf("1");
else
printf("0");
--num;
}
printf("\n");
}
int main()
{
int a = 0;
SETBIT(a, 5);
PrintBit(a);
return 0;
}
3、++ 和 -- 的操作
3.1 基本操作
其實這節知識點理解起來是很簡單的,只不過總有些學校喜歡出一些很拉跨的題目:
int i = 3; 問:(++i) + (++i) + (++i) 的值是多少?
我的建議是,看到這類題,直接空著,你也可以在下面添一句,“ 你禮貌嗎?”
這種錶達式,在任何編譯器下算出來的結果是不一樣的!
對於這種問題沒必要去爭論誰對誰錯, 如果有人想跟你杠的話,那麼你直接告訴他,你真的超級高水平。
好了,言歸正傳,我們來說一下 ++ 和 -- 的基本理解:
- 前置++ -- : 先自增(减),再使用
- 後置++ -- : 先使用,再自增(减) 如果沒有變量接收,那麼直接自增。
例子:
基本使用就是這麼多,接下來我們從匯編角度來深度理解一下:
3.2 從匯編角度深入理解 a++
既然我們知道,後置++ 是先使用後++,如果我們單純的就 ++ 一下呢,他這個值被使用到了哪裏去了呢?
int main()
{
int a = 0xDD;
int b = a++; //有b接收,那麼a的先使用是將a的值(內容),放到b中
int c = 0xEE;
c++; //沒有接收方,那麼"先使用",如何理解?
return 0;
}
vs2019編譯器反匯編:
結論:後置++ 完整的含義是先使用,在自增,如果沒有變量接收,那麼直接自增。
注意:在不同的編譯器可能處理過程不同,不過這是一個基本的研究過程,比單純的理論學習更嚴謹。
Calm, mature and precipitated
边栏推荐
猜你喜欢
Advantages of RFID warehouse management system solution
【1200. 最小绝对差】
每日一题-LeetCode1200-最小绝对差-数组-排序
解析互联网时代的创客教育技术
Difference between ApplicationContext and beanfactory (MS)
Solution of 5g unstable 5g signal often dropped in NetWare r7000 Merlin system
PS vertical English and digital text how to change direction (vertical display)
Jerry's ad series MIDI function description [chapter]
华为ensp模拟器 DNS服务器的配置
Can be displayed in CAD but not displayed in print
随机推荐
杰理之AD 系列 MIDI 功能说明【篇】
[server data recovery] a case of RAID5 data recovery stored in a brand of server
巅峰不止,继续奋斗!城链科技数字峰会于重庆隆重举行
Jerry's ad series MIDI function description [chapter]
Can be displayed in CAD but not displayed in print
render函数与虚拟dom
Huawei ENSP simulator layer 3 switch
Jerry's ad series MIDI function description [chapter]
宝塔 7.9.2 宝塔控制面板绕过 手机绑定认证 绕过官方认证
杰理之增加进关机前把触摸模块关闭流程【篇】
minidom 模塊寫入和解析 XML
c语言函数形参自增自减情况分析
奋斗正当时,城链科技战略峰会广州站圆满召开
五子棋 上班摸鱼工具 可局域网/人机
学习突围3 - 关于精力
A quick start to fastdfs takes you three minutes to upload and download files to the ECS
redis事务
Jmeter 之压测入门
Introduction to pressure measurement of JMeter
杰理之AD 系列 MIDI 功能说明【篇】