摘要:毋庸置疑,運算符號操作符就是進行語言的一些運算的,這些運算符雖然你在學語言的時候很不起眼,而在有些題目上還不讓用這些操作符來做題,但是,當你用到他們的時候,他們會給你意想不到的幫助。
目錄
C語言操作符指的是運算符號。毋庸置疑,運算符號(操作符)就是進行c語言的一些運算的,這些運算符雖然你在學c語言的時候很不起眼,而在有些題目上還不讓用這些操作符來做題,但是,當你用到他們的時候,他們會給你意想不到的幫助。
C語言中的符號分為10類:算術運算符、關系運算符、邏輯運算符、位操作運算符、賦值運算符、條件運算符、逗號運算符、指針運算符、求字節數運算符和特殊運算符
所謂優先級:就是計算的順序,在數學中有這么一個說法,就是先計算括號里面的,在計算外面的,先計算乘法除法,在計算加法減法。
優先級順序:(這里的優先順序估計一般人是記不住的,這些都是在百度上搜索的,大家可以當做筆記或者字典來看,找到自己不會的點學就完了)。
?1、優先級1級
結合方向 左結合(自左至右)
( ) 圓括號
-> 指向結構體成員運算符
2、優先級2級
結合方向 右結合(自右至左)單目運算符
! 邏輯非運算符
~ 按位取反運算符
++ 自增運算符
-- 自減運算符
-?負號運算符
(類型) 類型轉換運算符
* 指針運算符
& 地址與運算符
3、優先級3級
結合方向 左結合 雙目運算符
* 乘法運算符
/ 除法運算符
4、優先級4級
結合方向 左結合 雙目運算符
+ 加法運算符
5、優先級5級
結合方向 左結合 雙目運算符
<< 左移運算符
6、優先級6級
結合方向 左結合 雙目運算符
7、優先級7級
結合方向 左結合 雙目運算符
== 等于運算符 (判斷)
8、優先級8級
結合方向 左結合 雙目運算符
9、優先級9級
結合方向 左結合 雙目運算符
10、優先級10級
結合方向 左結合 雙目運算符
| 按位或運算符 舉例:0xfe|0xef 即為1111 1110 與1110 1111按位或運算則答案為:1111 1111 即0xff。
11、優先級11級
結合方向 左結合 雙目運算符
12、優先級12級
結合方向 左結合 雙目運算符
13、優先級13級
結合方向 右結合 三目運算符
? :?條件運算符
14、優先級14級
結合方向 右結合 雙目運算符
=?賦值運算符
+ = 加后賦值運算符 如s+=1表示s=s+1
- = 減后賦值運算符 如s-=1表示s=s-1
* = 乘后賦值運算符
/ = 除后賦值運算符
% = 取模后賦值運算符
< <= 左移后賦值運算符
>>=右移后賦值運算符
&= 按位與后賦值運算符
^=按位異或后賦值運算符
15、優先級15級
結合方向 左結合
,?逗號運算符
+? (進行加法運算)???-(進行減法運算)? ? ? ?*(在c語言中*代表是乘法)
/(在c語言中/代表除法):
對于除法運算,如果兩個數都是整數的話(即整數除法),則結果為整數,如果兩個數有一個數為浮點數,則結果就為小數
#include
int main(){ int a1 = 10 / 2; float a2 = 10 / 2.0; printf("%d/n", a1); printf("%f", a2); return 0;} %(在C語言中不是百分號這個是取模操作符)
取模操作符計算的是整數不能是小數,其中結果為余數。
移位操作符:移位是某數在內存中存儲的二進制位。
分類:左移操作符< ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?右移操作符>>
左移操作符<<
左移操作符是將數字在內存中存儲的二進制位向左移位。
先給大家講講進制吧
進制也就是進位計數制,是人為定義的帶進位的計數方法(有不帶進位的計數方法,比如原始的結繩計數法,唱票時常用的“正”字計數法,以及類似的tally mark計數)。 對于任何一種進制---X進制,就表示每一位上的數運算時都是逢X進一位。?十進制是逢十進一,十六進制是逢十六進一,二進制就是逢二進一,以此類推,x進制就是逢x進位。
進制的分類
16進制(0~15)? ? ? 8進制(0~7)? ? ? ? ? 2進制(0~1)
進制的表示形式:二進制以0b開頭,八進制以0開頭,16進制以0x開頭
由于在計算機存儲的是二進制我們具體給大家講二進制其他進制可以類比
由于二進制只有0和1,逢2進一,從右面開始,右面第一位是2^0,第二位是2^1,依次類推
?那我們拿5來舉例 5就是(前面的0省略),101(4+0+1=5);
這樣也就會了。
好接著我們來講左移操作符
還是拿5來舉例
?所以顯然左移操作符的作用是向左移動二進制位左邊丟棄右邊補0
用代碼這么表示? ? int a= a <<1;
那我們在進行移位操作的時候a本身有沒有變呢???
int main(){ int a = 5; int b = a << 1; printf("%d/n", a); printf("%d/n", b); return 0;}
?顯然a本身沒有變因為左移只是一種運算操作不會改變其地址;
講右移操作符之前先給大家普及一個小知識,我們整數在內存中存儲都是補碼,那什么是補碼呢??
說補碼那就不得不說原碼和反碼
原碼是啥呢?原碼就是一個整數本身的二進制 ,比如5的原碼就是101,又由于正數的原碼補碼反碼都相同所以補碼也是101。
先說一下從原碼到補碼的運算過程——是這樣運算的原碼——>反碼——>補碼
原碼變反碼是符號位不變剩下的所有位按位取反(0變1,1變0),反碼變補碼是反碼+1就是補碼。
所謂右移操作符就是二進制位向右移位
右移操作符分為兩種運算,一種是算術右移,第二種是邏輯右移,具體哪種運算就取決于編譯器進行哪種運算了(vs編譯器采用的是算術右移)
算術右移:右邊丟棄,左邊額補原來的符號位
邏輯右移:右邊丟棄,左邊補0
需要注意的是正數的原碼補碼反碼相同,而負數的原碼補碼反碼需要計算,因為通常在內存中存儲的是二進制補碼,而在打印的時候或者使用的時候我們用的是原碼,這時候,我們就需要將補碼變成原碼,怎么變呢??那當時剛才的反過來,補碼變反碼,那就是二進制位減一,反碼變原碼符號位不變其他位按位取反。
當我們進行左移或者右移的時候一定先轉化為原來二進制的補碼在進行移位操作
給大家舉個例子
位操作符有&(按位與)|(按位或)^(按位異或)
按位與:我是這么理解的,比如我與你肯定是你和我必須都存在,所以只有兩個都為1時才為1
按位或:或就是只要有一個就行,也就是兩個當中有1個為1才為1
按位異或:相同為0,相異為1
交換兩個數(不允許創作臨時變量)
我們都知道有這些操作符但都不知道該怎么應用,接下來我們進行按位異或的應用
首先先提個問題b^b=多少呢??
^(按位異或是相同為0相異為1),那可知b^b就應該是0了,那下面的代碼你就應該可以理解了
#include
int main(){ int a = 10; int b = 20; a = a^b; b = a^b; a = a^b; printf("a = %d b = %d/n", a, b); return 0;} 這里的b=a^b^b就是b=a;而a=a^a^b(就是a=b)。
賦值操作符
賦值就是把一個變量變成你想要的結果
我們通常用的賦值號就是=(值得注意的是==是相等,=是賦值)
復合賦值符+= -= *= /= %= >>= <<= &= |= ^=
但賦值時左值必須是一塊空間比如int
右值是一個值或者一塊空間的內容
注意:當我們用復合賦值符的時候盡量不要寫成連等例如y=b+2=c,這樣就讓人看不懂你的代碼可讀性就大大降低,所以我們寫代碼一定寫著清晰明了,讓別人看代碼一目了然。
! ? ? ? ? ? 邏輯反操作
什么是邏輯反操作?
反操作其實就是把真的改成假的,假的改成真的
#include
int main(){ int flag = 1;//1代表真 if (!flag)//!flag就代表假 { printf("1/n"); } else { printf("2/n"); } return 0;} - ? ? ? ? ? 負值
+ ? ? ? ? ? 正值
這里的正負值就是我們說的正負號也不用多說,因為這里是單目操作符,所以不要理解為加號和減號,比如加號兩邊是有兩個操作數所以是雙目操作符。
& ? ? ? ? ? 取地址
取地址符號就是取出變量的地址
#include
int main(){ int a = 10; //int* p = &a;//這里存放地址的變量叫做指針變量,其中int*是類型 printf("%p/n", &a);//取出a變量的地址 return 0;} sizeof ? ? ?操作數的類型長度(以字節為單位)
sizeof用來求數據類型或者變量的大小
#include
int main(){ int a = 2; printf("%d/n", sizeof(a));//計算變量a的大小 printf("%d/n", sizeof(int));//計算int類型的大小必須加() printf("%d/n", sizeof a);//計算變量a的大小 printf("%d/n", sizeof int);//計算int類型的大小必須加(),這里就會報錯 return 0;} ~ ? ? ? ? ? 對一個數的二進制按位取反
#include
int main(){ //按位取反 ~ //比如5 //5 的二進制位 00000000000000000000000000000101 // 按位取反 11111111111111111111111111111010 int a = 5; printf("%d/n", ~a); return 0;} 前置--:先--在使用
#include
int main(){ //前置--先--在使用 int a = 10; int b = --a; printf("%d/n", a); printf("%d/n", b); return 0;} ?
結果為啥是9 9呢?
我們這里是這樣操作的, 先--(就是a先--所以a變成9),在使用(把a=9賦給b);
后置--
#include
int main(){ //后置--先使用在-- int a = 10; int b = a--; printf("%d/n", a); printf("%d/n", b); return 0;} ?先使用(先把a=10賦給b所以b=10),在--(a--變成a=9);
前置++
#include
int main(){ //前置++先++在使用 int a = 10; int b = ++a; printf("%d/n", a); printf("%d/n", b); return 0;} ?先++(a先自己增加1所以a=11),在使用(把a=11賦給b,所以b=11);
后置++
#include
int main(){ //z后置++先使用在++ int a = 10; int b = a++; printf("%d/n", a); printf("%d/n", b); return 0;} 先使用(先將a=10賦給b,所以b=10),在++(a自己增加1,所以a=11)。
++,--總結:
如果是前置就先給自己增加或者減少,在賦值,如果是后置先把原來的值賦值在進行++或者--;
* ? ? ? ? ? 間接訪問操作符(解引用操作符)
#include
int main(){ int a = 10; int *p = &a;//指針變量p取出a的地址 *p = 20;//*p就是把存放a的地址解引用了,這里的*p就是原來的a, //這里是間接訪問把原來的a=10改成20 return 0;} (類型) ? ? ? 強制類型轉換
強制類型轉換就是把原本你不是這個常量屬于的類型,強制轉成某個類型
#include
int main(){ int a = (int)3.14;//把原本屬于double類型的強制轉換成int類型 printf("%d/n", a); //在比如隨機數種子 //srand((unsigned int)time(NULL)); return 0;}
這個我們前面也講過了,這里在復習下
我們講了有兩種特殊情況一種是sizeof(arr)計算的是整個數組的大小,一種是&arr指的的是整個數組的大小,剩下的都指的是數組首元素的地址。
#includeint main(){ int arr[5] = { 0,1,2,3,4 }; printf("%d/n", sizeof(arr)); return 0;}
當我們傳參的時候
#include
void test1(int arr[]){ printf("%d/n", sizeof(arr));//數組傳參,大小為指針的大小為4}void test2(char ch[]){ printf("%d/n", sizeof(ch));//數組傳參,大小為指針的大小為4}int main(){ int arr[10] = { 0 }; char ch[10] = { 0 }; printf("%d/n", sizeof(arr));//計算的是整個數組大小為10*4 printf("%d/n", sizeof(ch));//計算的是真個字符數組的大小為10*1 test1(arr); test2(ch); return 0;} 當我們進行數組傳參的時候傳的是地址也就是指針所以大小為4個字節
還要注意當我們想要計算整個數組大小的時候一定要main函數內部計算
>
>=
<
<=
!= ? 用于測試“不相等”
== ? ? ?用于測試“相等(經常在判斷時候使用,一定要和=(賦值號)區分開)。
&& ? ? 邏輯與 ? ? ? ? ? ? ? || ? ? ?邏輯或
這兩雖然是與前面按位與&,按位或|,意思相同
兩者區別是按位與和按位或是與二進制的計算有關
而邏輯與和邏輯或是進行判斷的
舉個例子
#includeint main(){ //判斷一個人的年齡處于什么狀態 int age = 0; scanf("%d", &age); if (0 < age < 18) { printf("未成年/n"); } else { printf("成年/n"); } return 0;}
這個代碼對么????
根據輸出結果判斷這個代碼肯定是錯的,那這里為啥會錯呢?這不應該和數學上是一樣的么?
在這個代碼是這樣理解的,你輸入25,進入if語句就判斷左半部分0<25結果為真,又25>18結果為真,所以判斷為真,輸出未成年。
那我們怎樣才能正確表示呢?這時邏輯操作符就派上用場了
#include
int main(){ //判斷一個人的年齡處于什么狀態 int age = 0; scanf("%d", &age); if (age>=0&&age<=18) { printf("未成年/n"); } else { printf("成年/n"); } return 0;}
#include
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;}//程序輸出的結果是什么 這個題如何考慮呢?
首先i=a++(后置++,先使用后++),這里先使用a=0&&++b為假所以++b不在計算,又0&&d++為假不計算,在打印的時候a在使用a++(a=1),其他的不計算所以計算結果為1234.
?
#include
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;}//程序輸出的結果是什么 這回我們把i換了,這回結果又是什么呢
首先a++,a不變,這時候變為a或什么,0||++b,結果為真所以b=3,c不變,前面是真,真或上啥都為真,d++不計算,最后打印a使用(a=1),所以結果我1334.
exp1 ? exp2 : exp3? ?解釋:表達式一成立則執行表達式二,輸出表達式二結果,不成立執行表達式三,輸出表達式三結果。
#includeint main(){ //舉例判斷兩個數的大小然后輸出大的數 int a = 10; int b = 20; /*if (a > b) { printf("%d/n", a); } else { printf("%d/n", b); }*/ //利用條件操作符 int ret = (a > b ? a : b);//a>b成立執行a,不成立則執行b。 printf("%d/n", ret); return 0;}
exp1, exp2, exp3, …expN
逗號表達式,就是用逗號隔開的多個表達式。
逗號表達式,從左向右依次執行。整個表達式的結果是最后一個表達式的結果。
?逗號表達式雖然執行表達式最后的結果但前面兩個表達式也是缺一不可的,前面兩個表達式要進行運算操作。
下標引用操作符常用于數組
#include
int main(){ //創建一個結構體變量 //以一個學生為例 struct stu { int height;//身高 int weight;//體重 }; struct stu stu = {180,120}; struct stu* ps = &stu; //printf("身高:%d/n體重:%d", s.height, s.weight);//.操作符為結構體成員訪問操作符 printf("身高:%d/n體重:%d/n", (*ps).height, (*ps).weight);//結構體指針訪問結構體成員 printf("身高:%d/n體重:%d", ps->height, ps->weight);// 結構體指針->結構體成員名 return 0;} 總結:結構體訪問
結構體.結構體成員名
結構體指針->結構體成員
表達式求值的定義:表達式求值的順序一部分是由操作符的優先級和結合性決定。 同樣,有些表達式的操作數在求值的過程中可能需要轉換為其他類型。
整形提升
什么是整形提升呢?
官方定義:C的整型算術運算總是至少以缺省整型類型的精度來進行的。 為了獲得這個精度,表達式中的字符和短整型操作數在使用之前被轉換為普通整型,這種轉換稱為整型 提升。
當我們進行比較低的類型進行計算的時候,由于計算機無法實現這種低的類型計算,計算機常常把類型轉換成整形進行計算
我們來舉幾個例子
比如我們要進行char和char類型的計算
#includeint main(){ char a = 5; //a的二進制 //00000000000000000000000000000101 //由于char類型是一個字節只能存放8個比特位所以需要截斷 //00000101 char b = 126; //00000000000000000000000001111110 //char類型進行截斷 //01111110 char c = a + b; //當我們進行a+b時候由于計算機無法實現char類型的計算 //這時我們就需要進行整形提升 //那怎樣整形提升呢?? //整形提升是按照變量的數據類型的符號位來提升 //所以我們補符號位 //a為00000000000000000000000000000101 //b為00000000000000000000000001111110 //兩者相加 //c變成10000011 //當我們進行打印的時候繼續整形提升 //整形提升后 //1111111111111111111111110000011--補碼 //又因為在內存中存儲的是補碼而我們要的是原碼 //1111111111111111111111110000010--反碼 //1000000000000000000000001111101原碼 printf("%d/n", c); return 0;}
我們再舉個例子
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;}
?
這個例子就很明顯由于a和b都需要整形提升所以不可能是原來的值,而c就可以打印?
舉例
int main(){ char c = 1; printf("%u/n", sizeof(c)); printf("%u/n", sizeof(+c)); printf("%u/n", sizeof(-c)); return 0;}
?這個也會很好的能說明當低類型的進行計算的時候(表達式計算時)也需要整形提升。
如果某個操作符的各個操作數屬于不同的類型,那么除非其中一個操作數的轉換為另一個操作數的類 型,否則操作就無法進行。下面的層次體系稱為尋常算術轉換。
這個算術轉換適用于int類型以上的類型進行轉換
long double
double
float
unsigned long int
long int
unsigned int
int
一般由低向高轉換
舉例
#includeint main(){ float f = 3.14; int num = f;//隱式轉換,會有精度丟失}
像這種如果要進行計算的話int類型必須轉化成float類型才能進行計算。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/123355.html
摘要:學習完多線程之后可以通過下面這些問題檢測自己是否掌握,下面這些問題的答案以及常見多線程知識點的總結在這里。可選數據結構與算法如果你想進入大廠的話,我推薦你在學習完基礎或者多線程之后,就開始每天抽出一點時間來學習算法和數據結構。 我自己總結的Java學習的系統知識點以及面試問題,已經開源,目前已經 35k+ Star。會一直完善下去,歡迎建議和指導,同時也歡迎Star: https://...
摘要:在位機器上,如果有個地址線,那一個指針變量的大小是個字節,才能存放一個地址。就是一個指針變量,也有自己的類型,指針變量的類型我們可以發現指針的定義方式是類型星號。也就是說存儲什么變量類型就用什么指針變量類型。 ...
摘要:瀏覽器的主要組成包括有調用堆棧,事件循環,任務隊列和。好了,現在有了前面這些知識,我們可以看一下這道題的講解過程實現步驟調用會將函數放入調用堆棧。由于調用堆棧是空的,事件循環將選擇回調并將其推入調用堆棧進行處理。進程再次重復,堆棧不會溢出。 JavaScript是前端開發中非常重要的一門語言,瀏覽器是他主要運行的地方。JavaScript是一個非常有意思的語言,但是他有很多一些概念,大...
摘要:實戰高并發程序設計這本書是目前點評推薦比較多的書,其特色是案例小,好實踐代碼有場景,實用。想要學習多線程的朋友,這本書是我大力推薦的,我的個人博客里面二十多篇的多線程博文都是基于此書,并且在這本書的基礎上進行提煉和總結而寫出來的。 學習的最好途徑就是看書,這是我自己學習并且小有了一定的積累之后的第一體會。個人認為看書有兩點好處:showImg(/img/bVr5S5); 1.能出版出...
摘要:當這些隱藏于幕后的工作者處理完委托給它們的事件后,它們會觸發綁定在這些事件上的回調函數去通知。習慣回調是一個單線程事件驅動的運行環境,也就是說,在里,任何事都是對事件的響應。 原文地址:https://codeburst.io/the-only-nodejs-introduction-youll-ever-need-d969a47ef219 作者:vick_onrails 摘要:這...
閱讀 2838·2021-11-15 11:39
閱讀 1816·2021-09-24 09:48
閱讀 1060·2021-09-22 15:36
閱讀 3581·2021-09-10 11:22
閱讀 2989·2021-09-07 09:59
閱讀 952·2021-09-03 10:28
閱讀 666·2021-09-02 15:15
閱讀 2738·2021-08-27 16:24