【C語言】8.C語言操作符詳解(1)

文章目錄

  • 1.操作符的分類
  • 2.?進制和進制轉換
  • 3.原碼、反碼、補碼
  • 4.移位操作符
    • 4.1 左移操作符
    • 4.2 右移操作符
  • 5.位操作符:&、|、^、~
    • 5.1 &:按位與
    • 5.2 |:按位或
    • 5.3 ^:按位異或
    • 5.4 ~:按位取反
    • 5.5 例題
      • 例題1
      • 例題2
      • 例題3
      • 例題4


1.操作符的分類

  1. 算術操作符: +-*/%

  2. 移位操作符: << ,>>

  3. 位操作符: &, |, ^

  4. 賦值操作符: =+=-=*=/=%=<<=>>=&=|=^=

  5. 單目操作符: ++--&*+-~sizeof(類型)

  6. 關系操作符: >>=<<===!=

  7. 邏輯操作符: &&||

  8. 條件操作符: ? :

  9. 逗號表達式: ,

  10. 下標引用: []

  11. 函數調用: ()

  12. 結構成員訪問: .->


2.?進制和進制轉換

進制轉換的教程網上比比皆是,而且視頻看起來肯定比文字清晰。這里就不過多贅述了。

我們需要掌握一下幾個:

  1. 2進制10進制
  2. 10進制2進制
  3. 2進制8進制和16進制
  4. 8進制和16進制2進制
  5. 8進制16進制
  6. 16進制8進制

3.原碼、反碼、補碼

整數的2進制表示方法有三種:

  1. 原碼

  2. 反碼

  3. 補碼

有符號整數的三種表示方法均有符號位和數值位兩部分,2進制序列中,最高位的1位是被當做符號位,剩余的都是數值位。

符號位都是用0表示“正”,用1表示“負”。

正整數的原、反、補碼都相同。

原碼:直接將數值按照正負數的形式翻譯成二進制得到的就是原碼。

反碼:正數反碼和原碼一樣。

補碼:正數補碼和原碼一樣。

負整數的三種表示方法各不相同。

原碼:直接將數值按照正負數的形式翻譯成二進制得到的就是原碼。(注意符號位)

反碼:將原碼的符號位不變,其他位依次按位取反就可以得到反碼。

補碼:反碼+1就得到補碼。


4.移位操作符

只有整數才能運用移位操作符。

4.1 左移操作符

例1:

#include <stdio.h>
int main()
{int num = 10;int n = num<<1;//10補碼:  00000000 00000000 00000000 00001010//10<<1補碼:0 00000000 00000000 00000000 00010100//這里最前面的0被丟掉了printf("n= %d\n", n);printf("num= %d\n", num);return 0;
}

打印:

n= 20
num= 10

例2:

#include <stdio.h>
int main()
{int num = -1;int n = num<<1;//-1原碼: 10000000 00000000 00000000 00000001//-1反碼: 11111111 11111111 11111111 11111110//-1補碼: 11111111 11111111 11111111 11111111
//-1<<1補碼:0 11111111 11111111 11111111 11111110//這里最前面的0被丟掉了printf("n= %d\n", n);printf("num= %d\n", num);return 0;
}

打印:

n= -2
num= -1

4.2 右移操作符

右移運算分兩種:

  1. 邏輯右移:左邊用0填充,右邊丟棄。

  2. 算術右移:左邊用原該值的符號位填充(正數左邊補0,負數左邊補1),右邊丟棄。

    右移是算術右移還是邏輯右移是取決于編譯器的。通常采用的都是算數右移。

例1:

#include <stdio.h>
int main()
{int num = -10;//-10原碼:10000000 00000000 00000000 00001010//-10反碼:11111111 11111111 11111111 11110101//-10補碼:11111111 11111111 11111111 11110110//邏輯右移:01111111 11111111 11111111 11111011 |0(這個0被丟棄了)//算術右移:11111111 11111111 11111111 11111011 |0(這個0被丟棄了)//這里采用算數右移//右移補碼:11111111 11111111 11111111 11111011//右移反碼:10000000 00000000 00000000 00000100//右移原碼:10000000 00000000 00000000 00000101--->-5int n = num>>1;printf("n= %d\n", n);printf("num= %d\n", num);return 0;
}

打印:

n= -5
num= -10

5.位操作符:&、|、^、~

雙目操作符:

  1. &:按位與
  2. |:按位或
  3. ^:按位異或

單目操作符:

  1. ~:按位取反

5.1 &:按位與

有0則0。

#include <stdio.h>
int main()
{int a = 6;// 6的補碼:00000000 00000000 00000000 00000110int b = -7;//-7的原碼:10000000 00000000 00000000 00000111//-7的反碼:11111111 11111111 11111111 11111000//-7的補碼:11111111 11111111 11111111 11111001int c = a & b;// 6的補碼:00000000 00000000 00000000 00000110//-7的補碼:11111111 11111111 11111111 11111001//a & b補碼::00000000 00000000 00000000 00000000-->0printf("n= %d\n", c);return 0;
}

打印:

n= 0

5.2 |:按位或

有1則1。

#include <stdio.h>
int main()
{int a = 6;// 6的補碼:00000000 00000000 00000000 00000110int b = -7;//-7的原碼:10000000 00000000 00000000 00000111//-7的反碼:11111111 11111111 11111111 11111000//-7的補碼:11111111 11111111 11111111 11111001int c = a | b;// 6的補碼:00000000 00000000 00000000 00000110//-7的補碼:11111111 11111111 11111111 11111001//a | b補碼:11111111 11111111 11111111 11111111//a | b反碼:10000000 00000000 00000000 00000000//a | b原碼:10000000 00000000 00000000 00000001-->-1printf("n= %d\n", c);return 0;
}

打印:

n= -1

5.3 ^:按位異或

相同為0,不同為1。

#include <stdio.h>
int main()
{int a = 6;// 6的補碼:00000000 00000000 00000000 00000110int b = -7;//-7的原碼:10000000 00000000 00000000 00000111//-7的反碼:11111111 11111111 11111111 11111000//-7的補碼:11111111 11111111 11111111 11111001int c = a ^ b;// 6的補碼:00000000 00000000 00000000 00000110//-7的補碼:11111111 11111111 11111111 11111001//a ^ b補碼:11111111 11111111 11111111 11111111//a ^ b反碼:10000000 00000000 00000000 00000000//a ^ b原碼:10000000 00000000 00000000 00000001-->-1printf("n= %d\n", c);return 0;
}

打印:

n= -1

5.4 ~:按位取反

按2進制位取反

#include <stdio.h>
int main()
{int a = 0;//0的原碼:00000000 00000000 00000000 00000000//~a補碼: 11111111 11111111 11111111 11111111//~a反碼: 10000000 00000000 00000000 00000000 //~a原碼: 10000000 00000000 00000000 00000001-->-1printf("n= %d\n", ~a);return 0;
}

打印:

n= -1

5.5 例題

例題1

不創建臨時變量(第三個變量),實現兩個整數的交換。

方法1:

int main() {int a = 3;int b = 5;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;
}

打印:

交換前:a=3 b=5
交換后:a=5 b=3

上面這個方法有點問題,如果a+b的和超過了一個整型數據的存儲大小,那么就計算不了了。


方法2:

int main() {int a = 3;int b = 5;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;
}

打印:

交換前:a=3 b=5
交換后:a=5 b=3

為什么呢?

因為異或操作符,相同兩個數異或為0。

3^3=0

a^a=0

0異或任何數都為數的本身 。

0^3=3

0^a=a

異或是支持交換率的。


例題2

編寫代碼實現:求一個整數存儲在內存中的二進制中1的個數。

int count_bit_onr(unsigned int n) {int count = 0;while (n) {if ((n % 2) == 1) {count++;}n = n / 2;}return count;
}int main() {int num = 0;scanf("%d", &num);int ret = count_bit_onr(num);printf("%d\n", ret);return 0;
}

輸入:

15

打印:

4

也可以這么寫:

int count_bit_onr(int n) {int i = 0;int count = 0;for (i = 0; i < 32; i++) {if ((n >> 1) & 1 == 1) {count++;}}return count;
}int main() {int num = 0;scanf("%d", &num);int ret = count_bit_onr(num);printf("%d\n", ret);return 0;
}

輸入-1會打印32

這個算法的原理:

-1補碼:11111111 11111111 11111111 11111111
1補碼: 00000000 00000000 00000000 00000001
-1&1=  00000000 00000000 00000000 00000001

不論-1的補碼前面多少個1,只要和1按位與后就只看最后一位是不是1。

然后運用移位操作符,將每一位都和1按位與,統計出一共多少個1。


其實還有更加巧妙地算法:

n=n&(n-1)

例如:n=11

n       = 1011
n-1     = 1010
n&(n-1) = 1010

因為n=n&(n-1),所以現在新的n是1010

n       = 1010
n-1     = 1001
n&(n-1) = 1000

因為n=n&(n-1),所以現在新的n是1000

n       = 1000
n-1     = 0111
n&(n-1) = 0000

從這三次變化里面我們可以看到,我們執行了一次n=n&(n-1),那么n最右面那個1就會消失。把所有的1都去掉后就變成0了。


例題3

寫一個代碼,判斷n是否為2的次方數。

首先我們先看看2的次方數:

000010
000100
001000
010000
100000

可以看出2的次方數里面只有1個1。

if (n & (n - 1) == 0) {printf("yes")
}

例題4

編寫代碼,將13二進制序列的第五位修改為1,然后改回0。

第5位改成1,第5位就和1或|,其他位都是0。

第5位改為0,第5位就和0與&,其他位都是1。

int main() {int a = 13;//13原碼:00000000 00000000 00000000 00001101//13補碼:00000000 00000000 00000000 00001101//16補碼:00000000 00000000 00000000 00010000//16|13:00000000 00000000 00000000 00011101-->29int n = 5;a = a | (1 << (n - 1));printf("%d\n", a);a &= ~(a << (n - 1));printf("%d\n", a);return 0;
}

打印:

29
13

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/13870.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/13870.shtml
英文地址,請注明出處:http://en.pswp.cn/web/13870.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

短視頻矩陣系統4年獨立開發正規代發布接口源碼搭建部署開發

1. 短視頻矩陣源碼技術開發要求及實現流程&#xff1a; 短視頻矩陣源碼開發要求具備視頻錄制、編輯、剪輯、分享等基本功能&#xff0c;支持實時濾鏡、特效、音樂等個性化編輯&#xff0c;能夠實現高效的視頻渲染和處理。開發流程主要包括需求分析、技術選型、設計架構、編碼實…

Web前端開發技術、詳細文章、(例子)html 列表、有序列表、無序列表、列表嵌套

目錄 列表概述 列表類型與標記符號 無序列表 語法&#xff1a; 語法說明&#xff1a; 無序列表標記的 type 屬性及其說明 代碼解釋 有序列表 基本語法 屬性說明 1、列表 o1標記的屬性 2、列表項li標記的屬性 有序列表 o1標記的屬性、值 代碼解釋 列表嵌套 基本…

如何將Qt pro工程文件 改成CMakeLists.txt

Qt pro工程管理文件&#xff0c;本人認為是很好用的&#xff0c;語法簡潔易懂&#xff0c;但是只能在QtCreator中使用&#xff0c;想用使用其它IDE比如Clion或者vs&#xff0c;CMakeLists是種通用的選擇&#xff0c;另外QtCreator的調試功能跟粑粑一樣。 一&#xff0c;思路 …

FreeBSD/Linux下的系統資源監視器排隊隊

bpytop bpytop 是一個基于 Python 的資源監視器&#xff0c;可以在 FreeBSD 上使用。它提供了對文件寫入磁盤、網絡、CPU 和內存占用的監視功能。 pkg install bpytop 或者用ports安裝 cd /usr/ports/sysutils/bpytop/ make install clean bashtop bashtop 也是一個基于 P…

化簡資源分配圖判斷是否發生死鎖

目錄 1.資源分配圖的概念 2.判斷是否發生死鎖 1.資源分配圖的概念 資源分配圖表示進程和資源之間的請求關系&#xff0c;例如下圖&#xff1a; P代表進程&#xff0c;R代表資源&#xff0c;R方框中 有幾個圓球就表示有幾個這種資源&#xff0c;在圖中&#xff0c;R1指向P1&a…

C++ RPC ORM 高速解析

支持所有常用編程語 https://capnproto.org/GitHub - capnproto/capnproto: Capn Proto serialization/RPC system - core tools and C library https://capnproto.org/capnproto-c-win32-1.0.2.zip 常用命令&#xff1a; capnp help capnp compile -oc myschema.capn…

java文件上傳時給pdf、word、excel、ppt、圖片添加水印

前言 在開發的過程中&#xff0c;因為文件的特殊性&#xff0c;需要給pdf、word、excel、ppt、圖片添加水印。添加水印可以在文件上傳時添加&#xff0c;也可以在文件下載時添加。因為業務的某些原因&#xff0c;文件需要在瀏覽器預覽&#xff0c;如果用戶將文件另存為則無法添…

算法與數據結構匯總

基本 數組 字符串 排序 矩陣 模擬 枚舉 字符串匹配 桶排序 計數排序 基數排序 回文&#xff1a;中心擴展 馬拉車 樹上啟發式合并 括號 數學表達式 字符串&#xff1a;前后綴分解。 貢獻法 分組&#xff1a; 【狀態機dp 狀態壓縮 分組】1994. 好子集的數目 【動態規劃】【前綴…

Excel中sum的跨表求和

#實際工作中&#xff0c;一個xlsx文件中會包含多個Excel表格&#xff0c;一般會有“總-分”的關系&#xff0c;如何把分表里的數字匯總到總表里呢&#xff1f; 一般有上圖所示的兩種表達方式。 可以使用通配符 *&#xff1a;代表任意個數、任意字符&#xff1b; &#xff1f;&…

51單片機的最小系統詳解

51單片機的最小系統詳解 1. 引言 在嵌入式系統中,51單片機被廣泛應用于各種小型控制器和嵌入式開發板中。相信很多人都接觸過51單片機,但是對于51單片機的最小系統卻了解得不夠深入。本文將從振蕩電路、電源模塊、復位電路、LED指示燈和調試接口五個方面詳細介紹51單片機的…

quartz定時任務

Quartz 數據結構 quartz采用完全二叉樹&#xff1a;除了最后一層每一層節點都是滿的&#xff0c;而且最后一層靠左排列。 二叉樹節點個數規則&#xff1a;每層從左開始&#xff0c;第一層只有一個&#xff0c;就是2的0次冪&#xff0c;第二層兩個就是2的1次冪&#xff0c;第三…

DOS學習-目錄與文件應用操作經典案例-attrib

新書上架~&#x1f447;全國包郵奧~ python實用小工具開發教程http://pythontoolsteach.com/3 歡迎關注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目錄 一.前言 二.使用 三.案例 一.前言 DOS系統中的attrib命令是一個用于顯示或更改文件&#…

設計模式——職責鏈(責任鏈)模式

目錄 職責鏈模式 小俱求實習 結構圖 實例 職責鏈模式優點 職責鏈模式缺點 使用場景 1.springmvc流程 ?2.mybatis的執行流程 3.spring的過濾器和攔截器 職責鏈模式 使多個對象都有機會處理請求&#xff0c;從而避免請求的發送者和接受者之間的耦合關系。將這個對象連成…

github設置項目分類

https://www.php.cn/faq/541957.html https://docs.github.com/zh/repositories/working-with-files/managing-files/creating-new-files

什么是回表,如何解決回表問題

下面表中:主鍵id是聚簇索引&#xff0c;name是輔助索引。 執行這樣一條SQL: select name from A where name"s;name字段是有索引&#xff0c;所以MYSQL在通過name進行査詢的時候&#xff0c;是需要掃描兩顆Btree樹的。 第一遍:先通過二級索引定位主鍵值1。第二遍:根據主鍵…

免費發布web APP的四個途徑(Python和R)

免費發布數據分析類&#x1f310;web APP的幾個途徑&#x1f4f1; 數據分析類web APP目前用來部署生信工具&#xff0c;統計工具和預測模型等&#xff0c;便利快捷&#xff0c;深受大家喜愛。而一個免費的APP部署途徑&#xff0c;對于開發和測試APP都是必要的。根據筆者的經驗…

word-形狀繪制、smartart、visio

一、人員架構圖繪制 小技巧&#xff1a; 1、ctrlshift水平復制 2、點擊圖形&#xff0c;右鍵設置為默認形狀 3、插入-形狀-右鍵-鎖定繪圖模式&#xff0c;按esc退出狀態 4、插入-形狀-新建繪圖畫布&#xff0c;代替組合問題 畫布中存在錨點&#xff0c;便于直線連接 二、s…

網絡安全相關面試題(hw)

網絡安全面試題 報錯注入有哪些函數 updatexml注入 載荷注入 insert注入 updata注入 delete注入 extractvalue&#xff08;&#xff09;注入 注入防御方法 涵數過濾 直接下載相關防范注入文件&#xff0c;通過incloud包含放在網站配置文件里面 PDO預處理,從PHP 5.1開始&…

electron中BrowserWindow的show事件沒有觸發踩坑記錄

class ElectronApi {static mainWindow;//主窗口createWindow() {try {// Create the browser window.this.mainWindow new BrowserWindow({width: 1200,height: 800,minHeight: 800,minWidth: 1200,webPreferences: {preload: preloadPath,// nodeIntegration: true,// conte…

windows怎么復制文件到vmware 中ubantu虛擬機,vmware中的虛擬機怎么聯網,NAT參數和DHCP參數。

目錄 windows怎么復制文件到vmware 中ubantu虛擬機 vmware中的虛擬機怎么聯網 NAT參數和DHCP參數。