【C語言】操作符詳解

目錄

一、算數操作符

?二、移位操作符

1.左移操作符

2.右移操作符

(1) 邏輯右移

(2) 算術右移

?(3)小總結

三、位操作符

四、賦值操作符

五、單目操作符

六、關系操作符

七、邏輯操作符

八、 條件操作符

九、逗號表達式

十、下標引用、函數調用和結構成員

1. [?]下標引用操作符

?2.? ( )函數調用操作符

3. 訪問一個結構的成員

十一、表達式求值

1.隱式類型轉換

2.算術轉換?

3.操作符的屬性

十二、操作符優先級


一、算數操作符

+? ? -? ? *? ?/? ?%

  • 除了 % 操作符之外,其他的幾個操作符可以作用于整數和浮點數
  • 對于 / 操作符如果兩個操作數都為整數,執行整數除法。但是,只要有浮點數參與運算就是浮點數除法
  • % 要求兩個操作數必須為整數,得到的是余數

?二、移位操作符

>>????????右移操作符

<<? ? ? ? 左移操作符

注意:移位操作符的操作數只能是整數

1.左移操作符

規則巧記:左邊拋棄,右邊補0

這里假設存的是 int n =15;的二進制 進行左移 n<<1;?如果n?在沒有被左移賦值的情況下,n自身的值是不會發生變化。(這里與自增自減不一樣)

在深層次看一下,一個數 n<<1,? 發現相當于該數 n * 2^1。n << 2;? ?等于 n?*?2^2?

2.右移操作符

(1) 邏輯右移

移位規則:右邊舍棄,左邊補0

假設內存 存放的是 -1 補碼的二進制? ?

(2) 算術右移

移位規則:右邊舍棄,左邊用原值的符號位進行填充

?

?(3)小總結

如果 算術右移與 邏輯右移 總是分不清。巧記:(算術右移,可以想象成 算數,既然算數肯定會有正負,進而想到 左邊填充的是原符號位)

注意:對于位操作符,不存在移動負數位,C語言標準并未規定

int num = 10;

num>> -1;? //error(不要多次一舉)

num? << 1;? // ok? 右移? -1? 這不相當于 左移 1 嘛。

三、位操作符

&? ? ? ? //按位與? 巧記:有0則0,其中? 一個數 a&1 可求 該數的每一個二進制位

|? ? ? ? ?//按位或? ?巧記:有1則1

^? ? ? ? //按位異或 巧記:相同為0,相異為1

注:操作數必須是整數

【例】1

#include<stdio.h>int main() 
{int a = 1;//0001int b = 2;//0010/** a& b;* 0001* 0010* 0000* * a|b* 0001* 0010* 0011* * a^b* 0001* 0010* 1100*/return 0;
}

接下來看一道面試題

【例】2?不能創建臨時變量(第三變量),實現兩個數的交換

解法一:

兩個數進行來回加減來進行兩個數的交換,通過調試的監視的窗口我們可以看到兩個數的交換?

?解法二:

#include<stdio.h>
int main()
{int a = 10;int b = 20;a = a ^ b;b = a ^ b;a = a ^ b;printf("%d %d",a,b);return 0;
}

從打印結果可以看到a 與 b的值進行了交換

【解析】^?按位異或 相同為0,相異為1(可以理解為 相同假,相異為真)

前面,提到 可以用a&1 該數的每一個二進制位,看下方例題

【例】編寫代碼,求一個整數存儲在內存中的二進制中1的個數

#include<stdio.h>
int main()
{int n = 10;int count = 0;//  0000 1010//  0000 0001int i = 0;for (i = 0; i < 32;i++){if (n & 1 == 1){count++;}		n = n>>1;}printf("%d",count);return 0;
}

?這里用到了 >> 和 ^

解法二:

#include<stdio.h>
int main()
{int n = 10;int count = 0;while (n) {if (n%2 == 1){count++;}n /= 2;}return 0;
}

這里的思路是 因為計算機存儲是二進制 0 和1 ,%2取余判斷是否為1,/2進行下一位?

?解法三:

#include<stdio.h>
int main()
{int n = -1;int i = 0;int count = 0;while (n){count++;n = n & (n - 1);//1111 1111 1111 1111 1111 1111 1111 1111//1111 1111 1111 1111 1111 1111 1111 1110//1111 1111 1111 1111 1111 1111 1111 1110}printf("%d ", count);return 0;
}

這里的優化 是借助 兩個數差1 進行按位與,一個一個位找1

四、賦值操作符

?=? 這是賦值符,不是等于!!!

賦值操作符? 給一個變量進行賦值 注意賦值操作符的優先級比較低(包括復合賦值符)

int age = 18;age = 20;  //對變量進行賦值

賦值操作符支持連續使用;

int a = 0;
int b = 10;
int c = 1;
a = b = c+1;  //這里是連續賦值

雖然可以連續賦值,但是代碼的可讀會下降

b = c+1;
a = b;
//這樣子是不是看著更用以理解

代碼的可讀性也是很重要的

接下來看復合賦值符都有哪些

+= 、-=、*= 、/= 、%= 、>>=? 、<<= 、&= 、 |= 、^=

int a = 10;
a = a+10;
//可以寫成這樣
a += 10;

其他復合賦值符同上方用法一致

五、單目操作符

單目操作符就是操作數只有一個

?sizeof ()括號里面不是類型時可以省略(),說到sizeof ,其中 size_t 是一種類型,是一種無符號整型的,size_t 就是為sizeof專門設計的一種類型,打印時使用%zd,但是size_t 在不同平臺下可能是 unsigned int? ?也有可能是? unsigned long long int?

sizeof(數組名) ,計算的是整個數組的大小

++前置,先對該數+1,然后再去使用這個數

++后置,相當于 先使用該數,然后在對該數進行 +1

-- 與上方的++同理

六、關系操作符

> 、?>= 、 < 、 <=? 、!= 、==

注意:== 這個是 等于

? ? ? ? ? ? =? ?這個是 賦值

七、邏輯操作符

&&? ? ? ? 邏輯與

||? ? ? ? ? ?邏輯或

要區分

& 與 &&? ?;? ?| 與 ||

1&2? ?--->? 0??

1&&2? --->? 1? ?(左邊為假,右邊無需計算,直接為假)

1? |? 2 --->? 3

1? ||? 2 ---> 1?(左邊為真,右邊無需計算,直接為真)

【例】1筆試題,求結果輸出的值

#include<stdio.h>
int main()
{int i = 0, a = 0, b = 2, c = 3, d = 4;i = a++ && ++b && d++;printf("a = %d\n b = %d\n c = %d\nd = %d\n", a, b, c, d);return 0;
}

? 【結果】a = 1 b = 2 c = 3 d = 4

解析? ??首先 a = 0 ,a++ ,是先使用后 +1,又有&&?(左邊為假,右邊無需計算,直接為假)

打印的是 a? = 1,其他值正常打印

【例】2?對這個題進行改編 a = 1

#include<stdio.h>
int main()
{int i = 0, a = 1, b = 2, c = 3, d = 4;i = a++ && ++b && d++;printf("a = %d\n b = %d\n c = %d\nd = %d\n", a, b, c, d);return 0;
}

【結果】 a = 2 b = 3 c = 3 d = 5

解析? a = 1時,左邊為真,后面表達式繼續進行計算,進而 a = 2, b = 3,c =3 ,d= 5

【例】3?對這個題進行改編 && 改為 ||? , 并求出i 的值

#include<stdio.h>
int main()
{int i = 0, a = 0, b = 2, c = 3, d = 4;i = a++ || ++b || d++;printf("a = %d\n b = %d\n c = %d\nd = %d\n", a, b, c, d);return 0;
}

【結果】 a = 1 b = 3 c = 3 d = 4? i = 1

解析 因為時邏輯或?(左邊為真,右邊無需計算,直接為真)雖然先使用 a 為假,但接下來的操作數 ++b , b = 3為真 進而后面無需計算。而 i 表達式里面有真 則 i = 1, 為真

八、 條件操作符

表達式1 ?表達式2 :表達式3;

唯一 一個三目操作符

在這里 看一個 求最大值的代碼

?a>b?a:b; //中文解釋 a>b 嗎?大于就是a, 不大于就是b

【例】求三個數的最大值?

#include<stdio.h>
int main() 
{int a = 1;int b = 2;int c = 3;int max = 0;max = a > b ? a : b;max = max > c ? max : c;printf("%d",max);return 0;
}

?這里是使用兩次條件操作符進行計算三個數中的最大值

九、逗號表達式

表達式1 , 表達式2 ,... , 表達式n

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

//代碼1
int a = 1;
int b = 2;
int c = (a>b, a=b+10, a, b=a+1);//逗號表達式

c 的結果是 13

逗號表達式可以對代碼進行優化

a = get_val();
count_val(a);
while (a > 0)
{//業務處理a = get_val();count_val(a);
}//使用逗號表達式可以改寫為
while (a = get_val(), count_val(a), a > 0)
{//業務處理
}

十、下標引用、函數調用和結構成員

1. [?]下標引用操作符

注意 操作數為 一個數組名 + 一個索引值

int arr[20]; //創建數組
// [ ] 的操作數 是 arr  和 20

?2.? ( )函數調用操作符

接受一個或者多個操作數:第一個操作數是函數名,剩余的操作數就是傳遞給函數的參數

#include <stdio.h>
void test1()
{printf("hehe\n");
}
void test2(const char* str)
{printf("%s\n", str);
}
int main()
{test1(); ??????//()作為函數調用操作符。test2("hello bit.");//()作為函數調用操作符。return 0;
}

3. 訪問一個結構的成員

.? ? ? ? 結構體.成員名

->? ? ? 結構體指針 -> 成員名

#include <stdio.h>
struct Stu
{char name[10];int age;char sex[5];double score;
};
void set_age1(struct Stu stu)
{stu.age = 18;
}
void set_age2(struct Stu* pStu)
{pStu->age = 18;//結構成員訪問
}
int main()
{struct Stu stu;struct Stu* pStu = &stu;//結構成員訪問stu.age = 20;//結構成員訪問set_age1(stu);pStu->age = 20;//結構成員訪問set_age2(pStu);return 0;
}

十一、表達式求值

表達式求值的順序一部分是由操作符的 優先級結合性 決定。
同樣,有些表達式的操作數在求值的過程中可能需要轉換為其他類型。

1.隱式類型轉換

整型算術運算總是至少以缺省整型類型的精度來進行的。
為了獲得這個精度,表達式中的字符和短整型操作數在使用之前被轉換為普通整型,這種轉換稱為整型提升

整型提升的意義

表達式的整型運算要在CPU的相應運算器件內執行,CPU內整型運算器(ALU)的操作數的字節長度
一般就是int的字節長度,同時也是CPU的通用寄存器的長度。因此,即使兩個char類型的相加,在CPU執行時實際上也要先轉換為CPU內整型操作數的標準長度。

通用CPU(general-purpose CPU)是難以直接實現兩個(8bit)字節直接相加運算(雖然機器指令中可能有這種字節相加指令)。所以,表達式中各種長度可能小于int長度的整型值,都必須先轉
換為int或unsigned int,然后才能送入CPU去執行運算。

//例
char a,b,c;
a = b + c;

在上述代碼中,b和c的值被提升為普通整型(int),然后再執行加法運算,加法運算完成之后,結果將被截斷,然后再存儲于a中

整型提升

整形提升是按照變量的數據類型的符號位來提升的

char c1 = -1;
變量c1的二進制位(補碼)中只有8個比特位:
1111111
因為 char 為有符號的 char
所以整形提升的時候,高位補充符號位,即為1
提升之后的結果是:
11111111111111111111111111111111
//正數的整形提升
char c2 = 1;
變量c2的二進制位(補碼)中只有8個比特位:
00000001
因為 char 為有符號的 char
所以整形提升的時候,高位補充符號位,即為0
提升之后的結果是:
00000000000000000000000000000001

無符號整形提升,高位補0

【例】1

int main()
{char a = 0xb6;short b = 0xb600;int c = 0xb6000000;if (a == 0xb6)printf("a");if (b == 0xb600)printf("b");if (c == 0xb6000000)printf("c");return 0;
}

【結果】c

實例的a,b要進行整型提升,但是c不需要整形提升a,b整形提升之后,變成了負數,所以表達式 a==0xb6 , b==0xb600 的結果是假,但是c不發生整形提升,則表達式 c==0xb6000000 的結果是真.

【a】1101 0110? 整型提升1111 1111 1111 1111 1111 1111 1101 0110

【b】1101 0110 0000 0000 整型提升1111 1111 1111 1111 1101 0110 0000 0000

【例】2

int main()
{char c = 1;printf("%u\n", sizeof(c));printf("%u\n", sizeof(+c));printf("%u\n", sizeof(-c));return 0;
}

【結果】1 4 4

實例2中的,c只要參與表達式運算,就會發生整型提升,表達式 +c ,就會發生提升,所以 sizeof(+c) 是4個字節。表達式 -c 也會發生整形提升,所以 sizeof(-c) 是4個字節,但是 sizeof(c) ,就是1個字節

2.算術轉換?

如果某個操作符的 各個操作數的類型不一樣,那么除非其中一個操作數的轉換為另一個操作數的類型,否則操作就無法進行。下面 尋常算術轉換

long double

double

unsigned long int?

long int

unsigned int

int

向上轉換??如果某個操作數的類型在上面這個列表中排名較低,那么首先要轉換為另外一個操作數的類型后執行運算

注意: 算數轉換要合理,否則可能會出現精度丟失
?

float pi = 3.14;???????int num = f;//num = 3 精度丟失

3.操作符的屬性

復雜表達式的求值有三個影響的因素。

  • 操作符的優先級
  • 操作符的結合性
  • 是否控制求值順序

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

十二、操作符優先級

點擊下方鏈接查看???????

鏈接:操作符優先級

注意:我們寫出的表達式如果不能通過操作符的屬性確定唯一的計算路徑,那這個表達式就是存在問題的。

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

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

相關文章

QT-如何使用RS232進行讀寫通訊

以下是一個使用Qt進行RS232通訊的具體示例&#xff0c;包括讀取和寫入數據的操作&#xff1a; #include <QCoreApplication> #include <QDebug> #include <QSerialPort> #include <QTimer>QSerialPort serial; // 串口對象void readData() {QByteArra…

GO學習之 微框架(Gin)

GO系列 1、GO學習之Hello World 2、GO學習之入門語法 3、GO學習之切片操作 4、GO學習之 Map 操作 5、GO學習之 結構體 操作 6、GO學習之 通道(Channel) 7、GO學習之 多線程(goroutine) 8、GO學習之 函數(Function) 9、GO學習之 接口(Interface) 10、GO學習之 網絡通信(Net/Htt…

UDS的DID(Data identification)

引言 DID是UDS中的一個重要概念&#xff0c;它代表著特定的數據標識符。DID用于標識和獲取ECU中的特定參數數據&#xff0c;如傳感器數據、狀態信息等。通過使用DID&#xff0c;診斷工具可以準確地獲取所需的數據&#xff0c;從而幫助診斷人員更好地了解車輛的狀態和性能。 D…

開發者必知:.gitignore 文件的魔法,助你管理項目文件如虎添翼!

前言&#xff1a; 在軟件開發的世界中&#xff0c;版本控制是一個至關重要的環節。而 Git 作為目前最流行的分布式版本控制系統之一&#xff0c;已經成為開發者不可或缺的工具。然而&#xff0c;在日常的開發過程中&#xff0c;有些文件是不適合被納入版本控制的&#xff0c;比…

leetcode242. 有效的字母異位詞

題目&#xff1a;leetcode242. 有效的字母異位詞 描述&#xff1a; 給定兩個字符串 s 和 t &#xff0c;編寫一個函數來判斷 t 是否是 s 的字母異位詞。 注意&#xff1a;若 s 和 t 中每個字符出現的次數都相同&#xff0c;則稱 s 和 t 互為字母異位詞。 示例 1: 輸入: s “…

【React | 前端】在React的前端頁面中,判斷某個變量值是否被定義?根據是否定義顯示不同的內容?

問題描述 在React的前端頁面中&#xff0c;判斷某個變量值是否被定義&#xff1f;根據是否定義顯示不同的內容&#xff1f; 問題場景 假如&#xff0c;現在有一個需求是設計一個新功能&#xff0c;新功能中要求新增一個之前沒有的變量&#xff0c;假設是計算某一個數組的長度…

基于Java+SpringBoot+Vue的數碼論壇系統設計與實現(源碼+LW+部署文檔等)

博主介紹&#xff1a; 大家好&#xff0c;我是一名在Java圈混跡十余年的程序員&#xff0c;精通Java編程語言&#xff0c;同時也熟練掌握微信小程序、Python和Android等技術&#xff0c;能夠為大家提供全方位的技術支持和交流。 我擅長在JavaWeb、SSH、SSM、SpringBoot等框架…

【C語言】深度剖析數據在內存中的存儲

一、數據類型詳細介紹 1、數據類型介紹 &#xff08;1&#xff09;基本的內置類型 //內置類型就是C語言自帶的類型char //字符數據類型 short //短整型 int //整形 long //長整型 long long //更長的整形 float //單精度浮點數 double …

微信小程序使用rich-text解析富文本字符串的時候,遇到image標簽圖片很大超過屏幕

場景&#xff1a; 使用uniapp開發微信小程序&#xff0c;解析富文本文章需求 用到的組件&#xff1a; u-view2.0的u-parse uniapp提供的rich-text 以上兩種組件都是解析富文本的作用&#xff0c;一般用于富文本解析場景&#xff0c;比如解析文章內容&#xff0c;商品詳情&am…

桶排序-1184:明明的隨機數

【題目描述】 明明想在學校中請一些同學一起做一項問卷調查&#xff0c;為了實驗的客觀性&#xff0c;他先用計算機生成了N個1到1000之間的隨機整數&#xff08;N≤100&#xff09;&#xff0c;對于其中重復的數字&#xff0c;只保留一個&#xff0c;把其余相同的數去掉&#x…

安防監控視頻匯聚平臺EasyCVR分發的FLV視頻流在VLC中無法播放是什么原因?

眾所周知&#xff0c;TSINGSEE青犀視頻匯聚平臺EasyCVR可支持多協議方式接入&#xff0c;包括主流標準協議國標GB28181、RTSP/Onvif、RTMP等&#xff0c;以及廠家私有協議與SDK接入&#xff0c;包括海康Ehome、海大宇等設備的SDK等。在視頻流的處理與分發上&#xff0c;視頻監控…

【jvm】jvm的生命周期

目錄 一、啟動二、執行三、退出 一、啟動 1.java虛擬機的啟動是通過引導類加載器bootstrap class loader創建一個初始類&#xff08;initial class&#xff09;來完成的&#xff0c;這個類是由虛擬機的具體實現指定的(根據具體虛擬機的類型) 二、執行 1.一個運行中的java虛擬機…

ORACLE行轉列、列轉行實現方式及案例

ORACLE行轉列、列轉行實現方式及案例 行轉列案例方式1.PIVOT方式2.MAX和DECODE方式3.CASE WHEN和GROUP BY 列轉行案例方式1.UNPIVOT方式2.UNION ALL 行轉列 案例 假設我們有一個名為sales的表&#xff0c;其中包含了產品銷售數據。表中有三列&#xff1a;product&#xff08;…

FPGA實踐 ——Verilog基本實驗步驟演示

0x00 回顧&#xff1a;AND/OR/NOT 邏輯的特性 AND&#xff1a;與門可以具有兩個或更多的輸入&#xff0c;并返回一個輸出。當所有輸入值都為 1 時&#xff0c;輸出值為 1。如果輸入值中有任何一個為 0&#xff0c;則輸出值為 0。 OR&#xff1a;或門可以具有兩個或更多的輸入…

【python】-【】

文章目錄 轉義字符和原字符二進制與字符編碼標識符和保留字變量的定義和使用變量字符串列表for 一、print會輸出①數字②字符串&#xff08;必須加引號&#xff09;③含有運算符的表達式&#xff08;例如 31 其中3&#xff0c;1是操作數&#xff0c;是運算符&#xff09;&#…

vector的模擬實現

什么是vector vector是一個封裝了動態大小數組的順序容器跟任意其它類型容器一樣&#xff0c;它能夠存放各種類型的對象。 模擬實現 實現前的準備 在實現vector之前&#xff0c;為了和庫里的區分開需要將實現的vector放在一個自定義的命名空間里。而且vector需要實現成模版…

論文閱讀 - Neutral bots probe political bias on social media

論文鏈接&#xff1a;Neutral bots probe political bias on social media | EndNote Click 試圖遏制濫用行為和錯誤信息的社交媒體平臺被指責存在政治偏見。我們部署中立的社交機器人&#xff0c;它們開始關注 Twitter 上的不同新聞源&#xff0c;并跟蹤它們以探究平臺機制與用…

超導熱催生meme,換湯不換藥的投機輪回

文/章魚哥 出品/陀螺財經 幣圈對炒作meme概念的熱情從未消亡過。 隨著一種名為LK-99的物質被發現&#xff0c;圍繞超導的興奮不僅激發了科學界&#xff0c;加密貨幣相關概念也與之沸騰。不出所料&#xff0c;與此前圍繞元宇宙、AI大肆炒作一樣&#xff0c;許多meme代幣已經出現…

關于MySQL中的binlog

介紹 undo log 和 redo log是由Inno DB存儲引擎生成的。 在MySQL服務器架構中&#xff0c;分為三層&#xff1a;連接層、服務層&#xff08;server層&#xff09;、執行層&#xff08;存儲引擎層&#xff09; bin log 是 binary log的縮寫&#xff0c;即二進制日志。 MySQL…

android開發之Android 自定義滑動解鎖View

自定義滑動解鎖View 需求如下&#xff1a; 近期需要做一個類似屏幕滑動解鎖的功能&#xff0c;右劃開始&#xff0c;左劃暫停。 需求效果圖如下 實現效果展示 自定義view如下 /** Desc 自定義滑動解鎖View Author ZY Mail sunnyfor98gmail.com Date 2021/5/17 11:52 *…