日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

C语言操作符详解

發布時間:2023/12/15 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C语言操作符详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

?作者簡介:嵌入式入坑者,與大家一起加油,希望文章能夠幫助各位!!!!
📃個人主頁:@rivencode的個人主頁
🔥系列專欄:玩轉C語言
💬推薦一款模擬面試、刷題神器,從基礎到大廠面試題👉點擊跳轉刷題網站進行注冊學習

目錄

  • 前言
  • 一.深度理解取余/取模運算
  • 二.續行符與轉義字符
  • 三.邏輯運算符
  • 四.位操作符
    • 1. 按位與 按位或 按位取反
    • 2.移位操作符
    • 實戰(重點)
  • 五.深入理解 a++
  • 六.操作符優先級

前言

所有關于運算的操作符,不管是邏輯運算還是位運算,都是先將變量在內存中提取在CPU內存寄存器中進行運算,然后計算的結果在寫回內存,所以我們操作的都是補碼,因為內存中存儲的都是數據的補碼,只有我們打印某個數據時才會涉及到原碼的概念。
建議在學習運算操作符之前先明白數據(整形)在內存中如何存儲

《數據到底在內存中如何存儲》

一.深度理解取余/取模運算


對于 / 操作符如果兩個操作數都為整數,執行整數除法。而只要有浮點數執行的就是浮點數除法。

想要得到小數部分一定一個操作數得是浮點數

% 操作符的兩個操作數必須為整數。返回的是整除之后的余數。


1.第一個問題整數的除法是如何取整的



為什么是這樣的一種取整方式呢。

其實C語言中的默認取整方式是向零取整

向零取整的函數


向負無窮方向取整的函數,返回不大于x的最大整數值



向正無窮方向取整的函數,返回不小x的最小整數值



四舍五入取整


取整方案對比:


這里你會發現就算不同的取整方式可能會得到同樣的值。

重點來了:取模和取余一樣嘛

先說結論

本質 1 取整:
取余:盡可能讓商,向零取整
取模:盡可能讓商,向-∞方向取整

而我們前面已經說了C語言默認的取整方案為向零取整,所以C語言中的%運用其實是在取余數。

被除數、除數、商、余數的關系:

如果a和d是兩個自然數,d非零,可以證明存在兩個唯一的整數 q 和 r,滿足 a = q*d + r 且0 ≤ |r|< |d|。。其中,q被稱為商,r 被稱為余數。


接下來來一個怪一點的:-10%3=?

在VS2013編譯器中:

在Python 2.7.12

為什么會出現不同的結果呢

根本原因是
C語言中 % 是取余數 — 得出的商向零取 整
Python中% 是取模 — 得出的商向負無窮取整

這樣我們就能解釋了,我們知道了商知道被除數和除數就可以求出余數


r余數的大小是取決于商的,而商的大小有取決與取整方式:

對任何一個大于0的數,對其進行0向取整和-∞取整,取整方向是一致的。故取模等價于取余

對任何一個小于0的數,對其進行0向取整和-∞取整,取整方向是相反的。故取模不等價于取余

這句是為什么C語言中通常將取余等價與取模,原因就是我們通常都是正數,而正數的取余才真正等價于取模。

同符號數據相除,得到的商,一定是正數(正數vs正整數),即大于0!=在對其商進行取整的時候,不管是向零取整還是向負無窮取整取整的方向都是一樣的所以所得的商也一樣,余數也一樣,所以取模等價于取余。

同符號時:取模等價于取余

不同符號時所得的商一定是負數,取模向負無窮取整,取余是向零取整則取整方向不一樣,所以所得的商不一樣,所得的余數也不一樣。

二.續行符與轉義字符

注意:續航符的后面不能帶任何東西(包括空格)

  • \的轉義功能:



    一道面試題:

    解析:


\0 與 數值0,NULL,和字符零’0’的區別


*NULL的數值其實是零,只不過NULL的類型是 void 類型


\0的ACSLL值也就是十進制表示也為0, 只不過\0的類型為字符型。


而 '0’字符零是ACSLL值為48 .

總結:\0 與 數值0,NULL數值相同都為0類型不同,

  • 回車與換行

    回車與換行本質是兩個概念:
    回車:光標回到當前行的最開始
    換行:光標移動到下一行

只不過 \n 既回車又換行。

利用回車做一個小程序:旋轉光標:

因為我們添加了 \r,所以每次打印都回到當前行的最開始覆蓋上一次的打印

利用回車做一個小程序:倒計時:

因為我們添加了 \r,所以每次打印都回到當前行的最開始覆蓋上一次的打印

三.邏輯運算符

&& 邏輯與
|| 邏輯或

邏輯與的特點:
1.所有表達式都成立才成立
2.從左向右結合
3.若有一個表達式不成立則后面的表達式不執行

所有表達式成立才成立:

若有一個表達式不成立則后面的表達式不執行:

注意:
這里成立與不成立的感念是真假的概念:非0為真,0為假

邏輯或的特點:
1.所有表達式有一個成立則成立
2.從左向右結合
3.若有一個表達式成立則后面的表達式不執行


都不成立才不成立:所有表達式全部執行一遍

筆試題:

解析:

變式1:

解析:

四.位操作符

1. 按位與 按位或 按位取反

所謂雙目運算符:有兩個操作數,操作數必須是整數

所有的運算都是要經過CPU來執行的,執行的過程中要想內存中提取數據,而存儲在內存中的數據全是補碼,所以我們的運算全是針對與數據的補碼

按位與運算 &
按位與運算符"&"是雙目運算符。 其功能是參與運算的兩數各對應二進制位相與。只有對應的兩個二進制位均為1時,結果位才為1 ,否則為0。

按位或運算 |
按位或運算符“|”是雙目運算符。 其功能是參與運算的兩數各對應的二進制位相或。只要對應的二個二進制位有一個為1時,結果位就為1。


求反運算~
求反運算符~為單目運算符,具有右結合性。 其功能是對參與運算的數的各二進位按位求反。


注意:符號位照樣取反

按位異或運算 ^
按位異或運算符“^”是雙目運算符。 其功能是參與運算的兩數各對應的二進制位相異或,當兩對應的二進制位相異時結果為1,相同結果為0,

按為異或的特點:
最好能記住解題塊的很
性質:
1.交換律 a^ b = b^a
2.結合律 a^ b ^ c = a^ (b^c)
3.任何數后零異或都是它本身
4. 自身與自身異或為0

其實上面的特點很好證明只要記住:相同為0,相異為1

實戰:交換兩個數

1.創建臨時變量

2. 不創建臨時變量

缺陷:當兩個數的足夠大時相加可能會溢出
3. 異或



其實知道異或的特性很快能做出來

2.移位操作符

左移: 最高位丟棄,最低位補零
右移:
1.無符號數:最低位丟棄,最高位補零[邏輯右移]
2.有符號數:最低位丟棄,最高位補符號位[算術右移]

注意:
有無 符號看的是數據的類型,與內存中保存的數據無關

左移: 最高位丟棄,最低位補零

右移:
1.無符號數:最低位丟棄,最高位補零[邏輯右移]


2.有符號數:最低位丟棄,最高位補符號位[算術右移]

如何理解丟棄:
左移或者右移都是計算,都要在CPU中進行,可是參與移動的變量,是在內存中的。所以需要先把數據移動到CPU內寄存器中,在進行移動,實際移動的過程中,是在寄存器中進行的,即大小固定的單位內。那么,左移右移一定會有位置跑到"外邊"的情況

所以還有一個結論:
我們左移右移都是針對內存中的數據而言的,而內存中的存儲的數據的補碼。

到底什么時候需要原碼:只有我們在打印某個數據時,從內存中拿出來的時候。

實戰(重點)

設置數據的指定比特位為1,其他比特位不變

設置數據的指定比特位為0,其他比特位不變

顯示數據的所有比特位,并記比特位中有多少個1

void ShowBits(int n) {int count = 0;int num = sizeof(n) * 8 - 1;while (num>=0){if (n&(1<<num)){printf("%d ",1);count++;}else{printf("%d ", 0);}num--;}printf("\n");printf("1的個數:%d\n", count); }

實驗效果:


左移:一般情況下左移一位就乘以2

//左移unsigned int a = 10;printf("%u\n", a << 1);printf("%u\n", a << 2);printf("%u\n", a << 3);return 0;


右移:一般情況下右移一位就除以2

這個我就不分析了, 與左移類似。

特殊情況:-1右移還是-1因為最高位補的是符號位

重點理解右移:
注意:
有無 符號看的是數據的類型,與內存中保存的數據無關


如果對整形如何存儲在內存中,或者對無符號類型的變量為什么能存儲負數有疑問請看——<數據到底在內存中如何存儲>

移位一個要注意的點:
+號的優先級比 移位操作符要高


有先級的概念一定要注意:拿捏不準就加上括號,準沒錯

五.深入理解 a++

a++ 在任何情況下都是先使用后++嘛

答案是否定的:

當有a++被使用時:
確實是先使用然后在完成自增

當有a++沒有被使用時:
a直接自增


接下來看一段復雜代碼:

在VS2013編譯器中:

在linux下gcc編譯器中:

為什么同一份代碼在不同的編譯器下,結果不同呢
vs2013 -->12
gcc —>10

根本原因寫出這種代碼:計算的途徑有很多種

  • vs2013 -->12


根本原因是編譯器先將i自增3次在指向i的相加
怎么計算方式并沒有違反操作符的優先級與結合性的規則

優先級:只會影響到兩個相鄰的操作符先執行哪個

  • gcc —>10


相當于先執行前面i++ ,讓i自增兩次i變成3,然后在執行前面兩個i相加 得3+3得6,最后讓最后一個i++,i變成4,最后相加的3+3+4=10

看完了匯編是不是還是有點沒理解:
其實這個式子與我們日常數學中的一個式子差不多:

  • 貪心法

C語言有這樣一個規則:每一個符號應該包含盡可能多的字符。也就是說,編譯器將程序分解成符號的方法是,從左到右一個一個字符的讀人,如果該字符可能組成一個符號,那么再讀人下一個字符時,判斷已經讀人的兩個字符組成的字符串是否可能是一個符號的組成部分;如果可能,繼續讀入下一個字符,重復上述判斷,直到讀人的字符組成的字符串已不再可能組成一個有意義的符號。這個處理的策略被稱為“貪心法”。需要注意的是,除了字符串與字符常量,符號的中間不能嵌有空白(空格、制表符、換行符等),比如:== 是單個符號,而= =是兩個等號。



貪心法簡單點說就是:盡可能多的匹配符號,組成C語言中多字符符號,例如:++ – &= <<= … 所以寫這些符號中間不要添加空格

看一個例子就明白了:

六.操作符優先級

復雜表達式的求值有三個影響的因素。
1. 操作符的優先級
2. 操作符的結合性
L-R :從左向右
R-L :從右向左
3. 是否控制求值順序。

邏輯或 || 邏輯與 && 條件操作符 ? : 逗號表達式

兩個相鄰的操作符先執行哪個取決于他們的優先級。如果兩者的優先級相同,取決于他們的結合性。

操作符優先級,越上面優先級越高

條件操作符:
格式:
如果表達式1為真,則執行表達式2,表達式2是整個表達式的結果
如果表達式1不成立,則執行表達式3,表達式3是整個表達式的結果

舉例:求兩個數的較大值

其實也可以實現嵌套,在某個表達式又搞一個 exp1? exp2:exp3

  • 逗號表達式
    逗號表達式,就是用逗號隔開的多個表達式。
    逗號表達式,從左向右依次執行。整個表達式的結果是最后一個表達式的結果。

總結

以上是生活随笔為你收集整理的C语言操作符详解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。