摘要:操作符的兩個(gè)操作數(shù)必須為整數(shù)。函數(shù)調(diào)用用作為函數(shù)調(diào)用操作符。訪問(wèn)一個(gè)結(jié)構(gòu)的成員結(jié)構(gòu)體成員名結(jié)構(gòu)體指針成員名還是熟悉的栗子在之前的博客請(qǐng)回答語(yǔ)言初識(shí)語(yǔ)言下入門(mén)的結(jié)構(gòu)體出現(xiàn)過(guò)的栗子名字圖鑒編號(hào)身高重量屬性類(lèi)型
學(xué)習(xí)操作符之前我們先對(duì)操作符分類(lèi),還和之前的初始c語(yǔ)言中一樣
+ - * / %
算數(shù)操作符本身很簡(jiǎn)單,不過(guò)有幾個(gè)注意事項(xiàng)
%
操作符之外,其他的幾個(gè)操作符可以作用于整數(shù)和浮點(diǎn)數(shù)。/
操作符如果兩個(gè)操作數(shù)都為整數(shù),執(zhí)行整數(shù)除法。而只要有浮點(diǎn)數(shù)執(zhí)行的就是浮點(diǎn)數(shù)除法。%
操作符的兩個(gè)操作數(shù)必須為整數(shù)。返回的是整除之后的余數(shù)。 int ret= 10 % 3;//% -- 取模(余) int ret = 10 / 3;//除法 -- 商 //當(dāng) /兩端都是整數(shù)的時(shí)候,執(zhí)行的都是整數(shù)的除法,兩端只要有一個(gè)是浮點(diǎn)數(shù),執(zhí)行的就是浮點(diǎn)數(shù)的除法 double ret2 = 10 / 3.0;//想得到小數(shù),必須保證除數(shù)或者被除數(shù)里面至少有一個(gè)是浮點(diǎn)數(shù)
移位操作符這里就涉及了把一個(gè)整數(shù)化為二進(jìn)制位,每一位的權(quán)重相當(dāng)于2的1次方,相當(dāng)于假如有四個(gè)1,則1 1 1 1每個(gè)1都表示不同的權(quán)重
第4位 | 第3位 | 第2位 | 第1位 |
---|---|---|---|
8 | 4 | 2 | 1 |
此外我們還得搞清楚整數(shù)的三種二進(jìn)制表達(dá)形式
原碼
反碼
補(bǔ)碼
對(duì)于整數(shù)的3種形式我們有這樣一個(gè)結(jié)論:
下面對(duì)一個(gè)整數(shù)5來(lái)舉例
再對(duì)-5來(lái)舉例
從這個(gè)例子我們可以看到
原碼在第32位中的0和1用來(lái)表示符號(hào)位,0表示正數(shù),1表示負(fù)數(shù),反碼同樣
反碼相當(dāng)于原碼的符號(hào)位不變,其他位按位取反得到的就是反碼
補(bǔ)碼就是反碼最低位+1
用VS調(diào)試看內(nèi)存我們就可以直觀看到
這里的ffff
就是16進(jìn)制的-1也就是二進(jìn)制下32個(gè)1,因?yàn)?6進(jìn)制下一個(gè)f
相當(dāng)于15,因此說(shuō)明內(nèi)存存儲(chǔ)的方式是利用補(bǔ)碼
總結(jié)一下:
- 一個(gè)整數(shù)在被存入內(nèi)存時(shí),存儲(chǔ)方式是利用的補(bǔ)碼
- 打印或者使用的時(shí)候,利用的是原碼
為什么這么規(guī)定呢?這涉及到加法器和減法器的原理,后面再展開(kāi)
移位規(guī)則:
- 左邊拋棄、右邊補(bǔ)0
int main(){ int a = 5; int b = a << 2; printf("%d/n",a); printf("%d/n", b); return 0;}
注:當(dāng)然a是不會(huì)被改變的
再舉個(gè)負(fù)數(shù)的例子:
int main(){ int a = -5; int b = a << 2; printf("%d/n",a); printf("%d/n", b); return 0;}
負(fù)數(shù)左移之后,打印出來(lái)是多少?
過(guò)程是先把-5補(bǔ)碼左移2位,然后按照負(fù)數(shù)的規(guī)律轉(zhuǎn)換成原碼,打印的時(shí)候是打印原碼結(jié)果
移位規(guī)則:
有點(diǎn)不同,稍微復(fù)雜
首先我們思考一下右移運(yùn)算本身分兩種:
左邊用0填充,右邊丟棄
左邊用原該值的符號(hào)位填充,右邊丟棄
到底如何移動(dòng),取決于編譯器的不同,我們常用的編譯器是算術(shù)右移
比如說(shuō)VS2019
注:這里的前提是在VS2019中,也即算術(shù)移位的前提下
int main(){ int a = -5; int b = a >> 1; printf("%d/n",a); printf("%d/n", b); return 0;}
具體過(guò)程就不細(xì)給了,按照規(guī)則,和左移稍微有一點(diǎn)區(qū)別
注:
對(duì)于移位運(yùn)算符,不要移動(dòng)負(fù)數(shù)位,這個(gè)是標(biāo)準(zhǔn)未定義的。
int num = 10;num>>-1;//error
已知位操作符有:
& //按位與| //按位或^ //按位異或
注:他們的操作數(shù)必須是整數(shù)。
問(wèn):位操作符用哪種二進(jìn)制位儲(chǔ)存形式進(jìn)行運(yùn)算?
答:因?yàn)槎际莾?nèi)存運(yùn)算,所以都是用的補(bǔ)碼
位操作符簡(jiǎn)單來(lái)說(shuō)就是兩個(gè)整數(shù)的每一位之間互相比較
輸入a | 輸入b | 結(jié)果 |
---|---|---|
0 | 0 | 0 |
1 | 0 | 0 |
0 | 1 | 0 |
1 | 1 | 1 |
看示例
int main(){ int a = 3; int b = -5; int c = a & b; printf("%d", c); return 0;}
輸入a | 輸入b | 結(jié)果 |
---|---|---|
0 | 0 | 0 |
1 | 0 | 1 |
0 | 1 | 1 |
1 | 1 | 1 |
int main(){ int a = 3; int b = -5; int c = a | b; printf("%d", c); return 0;}
兩個(gè)整數(shù)的二進(jìn)制位互相異或,其中二進(jìn)制位
相同為0
相異為1
輸入a | 輸入b | 結(jié)果 |
---|---|---|
0 | 0 | 0 |
1 | 0 | 1 |
0 | 1 | 1 |
1 | 1 | 0 |
int main(){ int a = 3; int b = -5; int c = a ^ b; printf("%d", c); return 0;}
int main(){ int num1 = 1; int num2 = 2; printf("%d/n",num1 & num2); printf("%d/n", num1 | num2); printf("%d/n", num1 ^ num2); return 0;}
不能創(chuàng)建臨時(shí)變量(第三個(gè)變量),實(shí)現(xiàn)兩個(gè)數(shù)的交換。
3個(gè)解法:
int main(){ int a = 3; int b = 5; //1 int c = 0;//臨時(shí)變量 printf("交換前: a=%d b=%d/n", a, b); c = a; a = b; b = c; //2 a = a + b; b = a - b; a = a - b; //3 - 異或 a = a ^ b; b = a ^ b;//a ^ b ^ b a = a ^ b;//a ^ b ^ a printf("交換后: a=%d b=%d/n", a, b); return 0;}
可以發(fā)現(xiàn)第一個(gè)解法不符合要求,因?yàn)橐獎(jiǎng)?chuàng)建臨時(shí)變量,剩下兩個(gè)方法可以巧妙解決,其中第三個(gè)方法最為巧妙,巧妙使用異或?qū)崿F(xiàn)轉(zhuǎn)換,可以嘗試化成二進(jìn)制舉例驗(yàn)證一下
編寫(xiě)代碼實(shí)現(xiàn):求一個(gè)整數(shù)存儲(chǔ)在內(nèi)存中的二進(jìn)制中1的個(gè)數(shù)。
想法:
我們說(shuō)如果由一個(gè)數(shù)a
&
1,那么就能得出這個(gè)數(shù)字二進(jìn)制最低位是0還是1那么如果我循環(huán)中不斷<<1再&1就可以計(jì)算出一個(gè)整數(shù)有幾個(gè)1
//方法1//解決不了負(fù)數(shù)#include int main(){ int num = 10; int count = 0;//計(jì)數(shù) while (num) { if (num % 2 == 1) count++; num = num / 2; } printf("二進(jìn)制中1的個(gè)數(shù) = %d/n", count); return 0;}//方法2:#include int main(){ int num = -1; int i = 0; int count = 0;//計(jì)數(shù) for (i = 0; i < 32; i++) { if (num & (1 << i)) count++; } printf("二進(jìn)制中1的個(gè)數(shù) = %d/n", count); return 0;}//這個(gè)方法還能更加優(yōu)化//方法3:#include int main(){ int num = 0; int i = 0; int count = 0;//計(jì)數(shù) scanf("%d", &num); while (num) { count++; num = num & (num - 1); } printf("二進(jìn)制中1的個(gè)數(shù) = %d/n", count); return 0;}//這種方式很好,達(dá)到了優(yōu)化的效果,但是難以想到。
賦值操作符可以改變之前的賦值
int weight = 120;//體重weight = 99;//不滿意就賦值double salary = 10000.0;//工資salary = 20000.0;//使用賦值操作符賦值。
當(dāng)然,賦值操作符可以連續(xù)賦值,但不是很建議這么寫(xiě)
a=x=y=100;
當(dāng)然:常量不能賦值
##4.1 復(fù)合賦值符
+=-=*=/=%=>>=<<=&=|=^=
這些運(yùn)算符都可以寫(xiě)成復(fù)合的效果
int x = 0;x = x+10;//普通x += 10;//復(fù)合賦值//其他運(yùn)算符一樣的道理。這樣寫(xiě)更加簡(jiǎn)潔。
已知單目操作符有:
! //邏輯反操作- //負(fù)值+ //正值& //取地址sizeof //操作數(shù)的類(lèi)型長(zhǎng)度(以字節(jié) 為單位)~ //對(duì)一個(gè)數(shù)的二進(jìn)制按位取反-- //前置、后置--++ //前置、后置++* //間接訪問(wèn)操作符(解引用操作符)(type) //強(qiáng)制類(lèi)型轉(zhuǎn)換
很多在之前的初識(shí)c語(yǔ)言中都已經(jīng)講過(guò),這里挑幾個(gè)記一下關(guān)鍵點(diǎn)
關(guān)于sizeof其實(shí)我們之前也已經(jīng)見(jiàn)過(guò)了,可以求變量(類(lèi)型)所占空間的大小。
常見(jiàn)的使用
有求數(shù)組的長(zhǎng)度:
int sz=sizeof(arr)/sizeof(arr[0]);
有求數(shù)組的大小
int arr[10]= {1,2,3,4,5,6};printf("%d/n",sizeof(arr));//40字節(jié)---4*10
有求int類(lèi)型數(shù)組或一個(gè)int的大小
printf("%d/n",sizeof(int [10]));//40字節(jié)---4*10printf("%d/n",sizeof(int));//4
小栗子:
void test1(int arr[]){ printf("%d/n", sizeof(arr));//(3)}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));//(1) printf("%d/n", sizeof(ch));//(2) test1(arr); test2(ch); return 0;}
注意從函數(shù)中傳過(guò)來(lái)的是指針,所以
sizeof
測(cè)的是 指針變量的大小,而主函數(shù)里面測(cè)的是整個(gè)數(shù)組中的大小
~
按位取反int main(){ int a = 0; //~ 按(內(nèi)存中補(bǔ)碼的2進(jìn)制)位取反 //00000000000000000000000000000000 //11111111111111111111111111111111 - 補(bǔ)碼 //11111111111111111111111111111110 - 反碼 //10000000000000000000000000000001 - 原碼 --> -1 printf("%d/n", ~a); return 0;}
有多組輸入的時(shí)候
while(~scanf("%d%d",&n,&m);
++ --
//++和--運(yùn)算符//前置++和--int main(){ int a = 10; int x = ++a; //先對(duì)a進(jìn)行自增,然后對(duì)使用a,也就是表達(dá)式的值是a自增之后的值。x為11。 int y = --a; //先對(duì)a進(jìn)行自減,然后對(duì)使用a,也就是表達(dá)式的值是a自減之后的值。y為10; return 0;}//后置++和--int main(){ int a = 10; int x = a++; //先對(duì)a先使用,再增加,這樣x的值是10;之后a變成11; int y = a--; //先對(duì)a先使用,再自減,這樣y的值是11;之后a變成10; return 0;}
注:注意值的變化
關(guān)系操作符:
>>=<<=!= ==
小結(jié)
還是不要搞錯(cuò)
=
和==
邏輯操作符有哪些:
&& 邏輯與|| 邏輯或
區(qū)分邏輯與和按位與
區(qū)分邏輯或和按位或
1&2----->01&&2---->11|2----->31||2---->1
舉個(gè)栗子:
int main(){ int i = 0, a = 0, b = 2, c = 3, d = 4; i = a++ && ++b && d++;//第一次結(jié)果 i = a++ || ++b || d++;//第二次結(jié)果 printf("a = %d/n b = %d/n c = %d/nd = %d/n", a, b, c, d); return 0;}
- 第一次的結(jié)果是:1 2 3 4
因?yàn)?&只要前面算出有0就不算后面的執(zhí)行了,所以a后置加加->a為1,而b和d不執(zhí)行
int main(){ int i = 0, a = 1, b = 2, c = 3, d = 4; i = a++ && ++b && d++; printf("a = %d/nb = %d/nc = %d/nd = %d/n", a, b, c, d); return 0;}
倘若這樣一改就是2 3 3 5了
- 第二次的結(jié)果是:1 3 3 4
因?yàn)樗愕?+b的時(shí)候已經(jīng)是真了,所以d++就不算下去了,于是自增的只有a和b
小結(jié):邏輯操作符只關(guān)注真與假
&&在遇到0(假)之后就不算后面的執(zhí)行了
||肯定是遇到1(真)之后
exp1 ? exp2 : exp3
之前就寫(xiě)過(guò)兩數(shù)之間的最大值
max = (a > b ? a : b);
逗號(hào)表達(dá)式,就是用逗號(hào)隔開(kāi)的多個(gè)表達(dá)式。
逗號(hào)表達(dá)式,從左向右依次執(zhí)行。整個(gè)表達(dá)式的結(jié)果是最后一個(gè)表達(dá)式的結(jié)果。
小栗子
int a = 1;int b = 2;int c = (a>b, a=b+10, a, b=a+1);
應(yīng)該從左到右依次執(zhí)行,因?yàn)槎禾?hào)表達(dá)式不只是算最后一個(gè)逗號(hào)里面的語(yǔ)句最后c應(yīng)該是13
int arr[10];//創(chuàng)建數(shù)組arr[9] = 10;//實(shí)用下標(biāo)引用操作符。
比如說(shuō)我想要打印數(shù)組中下標(biāo)為8的數(shù)
int main(){ int arr[10]={1,2,3,4,5,6,7,8,9,10}; printf("%d",arr[7]);//[]體現(xiàn)了下標(biāo)引用操作符的作用 printf("%d",7[arr]);//一般不用,沒(méi)用的小知識(shí)增加了 return 0;}
計(jì)算機(jī)在計(jì)算的時(shí)候是arr[7]->*(arr+7)->7[arr]
所以7[arr]也能符合要求
void test1(){ printf("函數(shù)調(diào)用test1()/n");}void test2(const char* str){ printf("%s/n", str);}int main(){ test1(); //用()作為函數(shù)調(diào)用操作符。 test2("Strength in Numbers");//用()作為函數(shù)調(diào)用操作符。 return 0;}
.
結(jié)構(gòu)體.成員名
->
結(jié)構(gòu)體指針->成員名
還是熟悉的栗子:
在之前的博客請(qǐng)回答c語(yǔ)言-初識(shí)c語(yǔ)言(下)【入門(mén)】的17.結(jié)構(gòu)體出現(xiàn)過(guò)的栗子
struct Pokemon{ char name[20];//名字 int id;//圖鑒編號(hào) float height; //身高 float weight;//重量 char fighting_type[20]; //屬性 char species[15]; //類(lèi)型};int main(){ struct Pokemon pikachu = { "Pikachu",25
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/123362.html
摘要:盡管如此,還具有高級(jí)的數(shù)據(jù)類(lèi)型和靈活性。它配備了大量的標(biāo)準(zhǔn)模塊,可用于程序庫(kù)。一些模塊提供如下功能通過(guò)這些很贊的特性,瞬時(shí)化身為面向過(guò)程的語(yǔ)言。開(kāi)發(fā)者可以便捷地將解釋器連接到一個(gè)使用編寫(xiě)的應(yīng)用程序,并能隨時(shí)用作擴(kuò)展。下一部分會(huì)繼續(xù)分享。 【編者按】本文作者是 Abhishek Jaiswal ,擅長(zhǎng) .NET、C#、Python 等多種語(yǔ)言的技術(shù)控。本文中,作者通過(guò)活潑有趣的口吻向大家...
摘要:年月宣布支持時(shí)間延長(zhǎng)到年。更詳細(xì)的發(fā)布列表參閱官網(wǎng)的版本號(hào)分為三段,形如。其中表示大版本號(hào),一般當(dāng)整體重寫(xiě),或出現(xiàn)不向后兼容的改變時(shí),增加表示功能更新,出現(xiàn)新功能時(shí)增加表示小的改動(dòng)如修復(fù)了某個(gè),只要有修改就增加。年公司正式發(fā)布。 < 返回索引頁(yè) Python語(yǔ)言簡(jiǎn)介 Python介紹及發(fā)展 介紹 Python 官方網(wǎng)站:https://www.python.org/, 大家可以到此處下...
摘要:有超過(guò)億用戶(hù),可謂是程序員解惑神站。問(wèn)答小組允許成員提問(wèn)并回答其它成員提出的問(wèn)題,很像。是新手學(xué)習(xí)和編程的理想網(wǎng)站。目前有萬(wàn)多注冊(cè)用戶(hù),幫助程序員度過(guò)關(guān)卡。是開(kāi)發(fā)人員的社交網(wǎng)站,是一個(gè)適合查詢(xún)各種編程語(yǔ)言和實(shí)戰(zhàn)技術(shù)的網(wǎng)站。 ...
摘要:如果在學(xué)習(xí)過(guò)程中有什么問(wèn)題可以關(guān)注我公眾號(hào)琉憶編程庫(kù)給我留言。有興趣可以深入學(xué)習(xí)最后附上學(xué)習(xí)的知識(shí)結(jié)構(gòu)圖譜,可以按著下面的這個(gè)知識(shí)結(jié)構(gòu)圖進(jìn)行學(xué)習(xí)不一定完整,更多資料,面試題,都可以關(guān)注公眾號(hào)琉憶編程庫(kù)獲取。 你好,是我——琉憶。PHP程序員面試系列圖書(shū)作者。 作為一名PHP開(kāi)發(fā)者過(guò)來(lái)人,也是經(jīng)歷了菜鳥(niǎo)到老手的過(guò)程,在此給那些想學(xué)PHP的同學(xué)指條路,即使你是轉(zhuǎn)行學(xué)PHP一樣可以學(xué)會(huì)PHP...
閱讀 2324·2021-11-15 11:38
閱讀 2453·2021-11-15 11:37
閱讀 2557·2021-08-24 10:00
閱讀 2918·2019-08-30 15:56
閱讀 1276·2019-08-30 15:53
閱讀 3713·2019-08-29 18:43
閱讀 2943·2019-08-29 17:01
閱讀 3266·2019-08-29 16:25