国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

這篇具有很好參考價(jià)值的文章主要介紹了C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

本篇博客全站熱榜最高排名:2
C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】
C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

一、算術(shù)操作符

因?yàn)镸arkDown的語(yǔ)法,所以用圖片的形式顯示
C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

  • 對(duì)于算術(shù)操作符而言有上面這五種,對(duì)于前面的【+】、【-】、【*】來(lái)說(shuō)操作數(shù)可以是整數(shù)或者浮點(diǎn)數(shù)
  • 對(duì)于【/】來(lái)說(shuō),叫做整除,結(jié)果就是我們?cè)跀?shù)學(xué)中說(shuō)到的。若是兩邊都是整數(shù),則執(zhí)行執(zhí)行整數(shù)除法;只有當(dāng)兩個(gè)操作符數(shù)中有一個(gè)數(shù)是小數(shù)的時(shí)候可以算作是浮點(diǎn)數(shù)除法
  • 對(duì)于【%】來(lái)說(shuō),叫做取余,結(jié)果就是我們?cè)跀?shù)學(xué)中說(shuō)到的余數(shù)。它的兩個(gè)操作數(shù)必須是整數(shù)

我們到VS中來(lái)驗(yàn)證一下

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】
C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】


再來(lái)看看取余操作符

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】
C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

二、移位操作符

接下去我們來(lái)說(shuō)說(shuō)移位操作符,它是一個(gè)為操作符,操作的是二進(jìn)制數(shù),因?yàn)楸容^重要,所以單獨(dú)拿出來(lái)做講解

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

1、前言小知識(shí) —— 原碼、反碼、補(bǔ)碼

在講述左移、右移操作符之前,要給讀者先介紹一下原碼、反碼、補(bǔ)碼,以便更好地理解二進(jìn)制位的概念

  • 對(duì)于一個(gè)數(shù)值來(lái)說(shuō),可以由不同的進(jìn)制來(lái)表示,在計(jì)算機(jī)內(nèi)部,有【二進(jìn)制、八進(jìn)制、十進(jìn)制、十六進(jìn)制】
  • 假設(shè)一個(gè)十進(jìn)制數(shù)15,它的八進(jìn)制表示形式即為17,十六進(jìn)制為F,二級(jí)制為1111。這個(gè)要涉及到每一位上的權(quán)重概念,這里的內(nèi)容很多不好敘述,可以看看——> 進(jìn)制轉(zhuǎn)換(二進(jìn)制、八進(jìn)制、十進(jìn)制、十六進(jìn)制)
    C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】
  • 對(duì)于一個(gè)整數(shù)來(lái)說(shuō),在內(nèi)存中的二級(jí)制表示形式有【原碼】【反碼】【補(bǔ)碼】三種,它們寫成二進(jìn)制位的形式也就是32位二進(jìn)制,例如整數(shù)4,它的原碼即為0 0000000000000000000000000000100??梢钥吹轿覍⒆罡呶缓秃竺娴?1位做了一個(gè)分隔,因?yàn)閷?duì)于32個(gè)二進(jìn)制位來(lái)說(shuō),最高位叫做符號(hào)位
  • 符號(hào)位是0,表示正整數(shù)
  • 符號(hào)位是1,表示負(fù)整數(shù)
  • 而對(duì)于一個(gè)正數(shù)來(lái)說(shuō),它的原碼、反碼、補(bǔ)碼都是相同的;對(duì)于一個(gè)負(fù)數(shù)來(lái)說(shuō),它的反碼等于原碼除符號(hào)位外其余按位取反,補(bǔ)碼等于反碼 + 1
    C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

看到這里的讀者可能會(huì)很好奇,不是要講移位操作符嗎,為什么要先講這些呢?

  • 在這里你需要記住這一句話,它在后面的位操作符中同樣適用

在計(jì)算機(jī)中都是使用二進(jìn)制數(shù)的補(bǔ)碼進(jìn)行運(yùn)算的,但是在計(jì)算完之后輸出的結(jié)果都要再轉(zhuǎn)化為原碼的形式

2、左移操作符【擴(kuò)大2倍】

有了上面的知識(shí)做鋪墊,接下去就讓我們真正地進(jìn)入移位操作符的學(xué)習(xí)??

??【移位規(guī)則】:左邊拋棄、右邊補(bǔ)0

  • 首先來(lái)看到的是要計(jì)算一個(gè)數(shù)字4左移1位后的,將其運(yùn)算后的結(jié)果放到b里面去。那我們知道,在內(nèi)存中進(jìn)行計(jì)算都是使用補(bǔ)碼的形式,因?yàn)橐来螌懗?的原、反、補(bǔ)碼,因?yàn)樗钦麛?shù),所以均是相同的
int main(void)
{
	int a = 4;
	//0 0000000000000000000000000000100 - 4的原碼
	//0 0000000000000000000000000000100 - 4的反碼
	//0 0000000000000000000000000000100 - 4的補(bǔ)碼

	int b = a << 1;		//把a(bǔ)向左移動(dòng)一位
	printf("a = %d, b = %d\n", a, b);
	return 0;
}

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

  • 通過(guò)圖示就可以看出,將一個(gè)二進(jìn)制數(shù)進(jìn)行左移運(yùn)算,要執(zhí)行的規(guī)則是左邊丟棄,右邊補(bǔ)0,其實(shí)這起到的效果就是將原來(lái)的數(shù)乘上一個(gè)2倍,因?yàn)閷?duì)于每一個(gè)相鄰的二進(jìn)制數(shù)說(shuō),均是一個(gè)2倍的關(guān)系,因?yàn)槠溥\(yùn)行出來(lái)的結(jié)果即為4 * 2 = 8,也就是b = 8

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

  • 可以看到,這個(gè)原來(lái)的數(shù)字a是不會(huì)發(fā)生變化的,只是對(duì)其進(jìn)行一個(gè)運(yùn)算,將其運(yùn)算之后的結(jié)果放到b中去而已

接著我們?cè)賮?lái)看看負(fù)數(shù)的情況

  • 對(duì)于正數(shù)來(lái)說(shuō),其實(shí)看不出其在內(nèi)部中的數(shù)值變換,因?yàn)樵⒎?、補(bǔ)碼均是相同的;但是對(duì)于負(fù)數(shù)來(lái)說(shuō)可不一樣了,可以看到下面是對(duì)-4進(jìn)行一個(gè)移位的操作,寫出其補(bǔ)碼之后就開(kāi)始了移位操作
int main(void)
{
	int a = -4;
	//1 0000000000000000000000000000100 - -4的原碼
	//1 1111111111111111111111111111011 - -4的反碼
	//1 1111111111111111111111111111100 - -4的補(bǔ)碼

	int b = a << 1;		//把a(bǔ)向左移動(dòng)一位

	//1 1111111111111111111111111111000 - -4移位后的的補(bǔ)碼
	//1 1111111111111111111111111110111 - -4移位后的的反碼
	//1 0000000000000000000000000001000 - -4移位后的的原碼
	printf("a = %d, b = %d\n", a, b);
	return 0;
}

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

  • 但是在移位之后我們還要將二進(jìn)制數(shù)轉(zhuǎn)換為原碼的形式,上面說(shuō)到過(guò),雖然在計(jì)算機(jī)內(nèi)部是采用補(bǔ)碼的形式進(jìn)行計(jì)算的,但是輸出打印在屏幕是是采用原碼的形式,所以還是要按照負(fù)數(shù)原、反、補(bǔ)碼的規(guī)則進(jìn)行一個(gè)轉(zhuǎn)換,最后得出的結(jié)果再轉(zhuǎn)換為十進(jìn)制便是8

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

3、右移操作符【縮小2倍】

講完左移操作符,接下去我們?cè)賮?lái)講講右移操作符>>

??【移位規(guī)則】:
① 邏輯移位
??左邊用0填充,右邊丟棄
② 算術(shù)移位
??左邊用原該值的符號(hào)位填充,右邊丟棄

  • 可以看到,對(duì)于右移操作符,和左移不同的是它的運(yùn)算規(guī)則比較復(fù)雜,因?yàn)樵诓煌幾g器下對(duì)于移位后的符號(hào)位填充是有所不同的,但是在VS下采用的是第二種算術(shù)移位,所以我以此作為講解

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

  • 因?yàn)樯厦嬉呀?jīng)給出過(guò)代碼了,因此這里不做展示,從運(yùn)行結(jié)果可以看出對(duì)于右移運(yùn)算來(lái)說(shuō)就是一個(gè)縮小的情況,但具體是如何計(jì)算的呢,我們通過(guò)畫圖來(lái)看看

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】


然后我們?cè)賮?lái)看看負(fù)數(shù)的情況

  • 對(duì)于負(fù)數(shù)來(lái)說(shuō)還是一樣,在計(jì)算機(jī)內(nèi)部會(huì)將其轉(zhuǎn)化為補(bǔ)碼的形式進(jìn)行運(yùn)算,然后再內(nèi)部計(jì)算完畢后還要將其轉(zhuǎn)換為原碼的形式

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

  • 下面是它在內(nèi)存中轉(zhuǎn)換的情況

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】
【注意?】
??對(duì)于移位運(yùn)算符,不要移動(dòng)負(fù)數(shù)位,這個(gè)是標(biāo)準(zhǔn)未定義的

int main(void)
{
	int a = 5;
	int b = a << -1;	//error
	return 0;
}

對(duì)于這個(gè)移位操作符來(lái)說(shuō),你可能會(huì)決定它不是很常用,所以也沒(méi)必要很認(rèn)真地學(xué)習(xí),其實(shí)這就錯(cuò)了,那是因?yàn)槟憬佑|得還不夠多,其實(shí)在某些特定的場(chǎng)合下,它可以起到非常之大的作用,后面有一道綜合例題我會(huì)進(jìn)行講解?

三、位操作符

好,接下去我們來(lái)講講位操作符,這也是很多同學(xué)長(zhǎng)期以來(lái)沒(méi)有搞懂的一塊

1、按位與【&】

??【規(guī)則】:全1為1,有0為0

  • 一樣,對(duì)于位運(yùn)算來(lái)說(shuō),在計(jì)算機(jī)中進(jìn)行運(yùn)算的是一個(gè)數(shù)的補(bǔ)碼形式,然后打印在屏幕上是原碼的形式
//按位與 - 全1為1,有0為0
int main(void)
{
	int a = 3;
	int b = -5;
	int c = a & b;
	printf("c = %d\n", c);
	//00000000000000000000000000000011 - 3的原碼、反碼、補(bǔ)碼

	//10000000000000000000000000000101 - -5的原碼
	//11111111111111111111111111111010 - -5的反碼
	//11111111111111111111111111111011 - -5的補(bǔ)碼

	//00000000000000000000000000000011
	//11111111111111111111111111111011
	//00000000000000000000000000000011 - 3【補(bǔ)碼即為原碼】
	return 0;
}
  • 根據(jù)按位與的運(yùn)算規(guī)則,我們就可以得出最后的結(jié)果為3

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

2、按位或【|】

??【規(guī)則】:有1為1,全0為0

//按位或 - 有1為1,全0為0
int main(void)
{
	int a = 3;
	int b = -5;
	int c = a | b;
	printf("c = %d\n", c);
	//00000000000000000000000000000011 - 3的原碼、反碼、補(bǔ)碼

	//10000000000000000000000000000101 - -5的原碼
	//11111111111111111111111111111010 - -5的反碼
	//11111111111111111111111111111011 - -5的補(bǔ)碼

	//00000000000000000000000000000011
	//11111111111111111111111111111011
// --------------------------------------
	//11111111111111111111111111111011 |
	//11111111111111111111111111111010 |
	//10000000000000000000000000000101 | - 5
	return 0;
}
  • 根據(jù)按位或的運(yùn)算規(guī)則,我們就可以得出最后的結(jié)果為-5

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

3、按位異或【^】

??【規(guī)則】:相同為0,相異為1

//按位異或 - 相同為0,相異為1
int main(void)
{
	int a = 3;
	int b = -5;
	int c = a ^ b;
	printf("c = %d\n", c);
	//00000000000000000000000000000011 - 3的原碼、反碼、補(bǔ)碼

	//10000000000000000000000000000101 - -5的原碼
	//11111111111111111111111111111010 - -5的反碼
	//11111111111111111111111111111011 - -5的補(bǔ)碼

	//00000000000000000000000000000011
	//11111111111111111111111111111011
// --------------------------------------
	//11111111111111111111111111111000
	//11111111111111111111111111110111
	//10000000000000000000000000001000 -> -8
	return 0;
}
  • 根據(jù)按位異或的運(yùn)算規(guī)則,我們就可以得出最后的結(jié)果為-8

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

  • 對(duì)于異或有兩個(gè)很重要的結(jié)論要記,在使用異或操作符的時(shí)候基本都是用到它們

??兩個(gè)相同的數(shù)異或?yàn)?a ^ a = 0
??任何數(shù)和0異或均為那個(gè)數(shù)本身a ^ 0 = a


4、按位取反【~】

??【規(guī)則】:1變0, 0變1

  • 對(duì)于按位取反來(lái)說(shuō)不考慮符號(hào)位,也就是將所有的1變成0,所有的0變成1即可。但是不要忘了那句口訣,對(duì)于負(fù)數(shù)的補(bǔ)碼來(lái)說(shuō)是需要再進(jìn)行一個(gè)轉(zhuǎn)換的
int main(void)
{
	int a = 0;
	int b = ~a;
	printf("b = %d\n", b);

	//00000000000000000000000000000000
	//11111111111111111111111111111111  按位取反【補(bǔ)碼】	
	//11111111111111111111111111111110	【反碼】
	//10000000000000000000000000000001 -> -1【原碼】
	return 0;
}
  • 那么0按位取反之后就變成了-1

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

??兩道很變態(tài)的面試題??

介紹完了所有的位操作符符,接下去我們馬上來(lái)檢驗(yàn)一下學(xué)習(xí)的成果, 下面是兩道歷年面試中的考題,比較復(fù)雜而且也很多的位運(yùn)算在里面,因?yàn)槟贸隼沧鲋v解

① 兩數(shù)交換

首先第一道比較容易一些,對(duì)于兩個(gè)數(shù)的交換相信大家是非常熟悉的

  • 我們可以使用第三方臨時(shí)變量做一個(gè)存放;若是放到個(gè)單獨(dú)的函數(shù)中進(jìn)行交換的操作,那么就要進(jìn)行對(duì)應(yīng)的傳址操作,如果是在C++中的話還可以使用引用操作符&
  • 但是在本文中,我要使用位運(yùn)算來(lái)進(jìn)行實(shí)現(xiàn),主要是使用到異或位運(yùn)算^

在這之前,我們通過(guò)加減的方式來(lái)試著交換一下這兩個(gè)數(shù)

int main(void)
{
	int a = 3;
	int b = 5;
	printf("a = %d, b = %d\n", a, b);

	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;
}
  • 可以看到,變量中的兩個(gè)數(shù)發(fā)生了交換,我們來(lái)分析一下它們是如何發(fā)生交換的
  • 首先執(zhí)行的是a = a + b,也就是把a(bǔ) + b的值放到a里面去,接著第二句是b = a - b,因?yàn)榻?jīng)過(guò)上面一句的運(yùn)算,a里面存放的已經(jīng)是a + b的和了,那么再減去b的話也就是a,因?yàn)槲覀円粨Q兩個(gè)值,所以就是要將a的值放到變量b里面去,所以拿b來(lái)接受
  • 那此時(shí)b里面存放的就是a的值了,但是a里面存放的還是a + b的值,所以第三句a = a - b計(jì)算出來(lái)的結(jié)果就是b的值,將其存入變量a中
  • 那么此時(shí)打印出來(lái)a與b值便是交換之后的值

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】


  • 但其實(shí)對(duì)于上面這種方法是有缺陷的,若是a與b是兩個(gè)很大的數(shù)時(shí),就會(huì)出現(xiàn)數(shù)據(jù)溢出的情況,所以在下面我要使用異或^的方法來(lái)運(yùn)算
  • 可以看到使用異或來(lái)進(jìn)行運(yùn)算的時(shí)候總體的思路還是不變的,將加減運(yùn)算符改成異或運(yùn)算符之后,就需要使用到我們上面講到過(guò)的異或拓展規(guī)則??
  • 首先第一句a = a ^ b將a和b異或后的結(jié)果暫存到a里面去,然后再去異或b的話就相當(dāng)于是a ^ b ^ b,根據(jù)規(guī)則便可以得出結(jié)果為a,將其放入b中
  • 然后第三句a = a ^ b,就相當(dāng)于是a ^ b ^ a,那么結(jié)果就是b,將其放入a中
int main(void)
{
	int a = 3;
	int b = 5;
	printf("a = %d, b = %d\n", a, b);

	a = a ^ b;
	b = a ^ b;		//a ^ b ^ b = a ^ 0 = a
	a = a ^ b;		//a ^ b ^ a = b ^ 0 = b

	printf("a = %d, b = %d\n", a, b);
	return 0;
}
  • 最后打印出來(lái)就是交換之后的結(jié)果

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

通過(guò)這道題,相信你對(duì)異或的運(yùn)算一定可以掌握得很好,平常在進(jìn)行OJ刷題的時(shí)候,其實(shí)也是可以使用到的,但這前提是你要會(huì)靈活使用

② 進(jìn)制定位

接下去第二道是比較困難的,因?yàn)榻Y(jié)合了我們上面所學(xué)習(xí)的所有位操作符

【需求1】:將變量a的第n位置為1

  • 看到這個(gè)需求你可能有點(diǎn)懵,我來(lái)解釋一下,這個(gè)第n位值的不是十進(jìn)制位,而是二進(jìn)制位,也就是將一個(gè)變量在內(nèi)存中的32位中的某一位置為1,但是又不能改變其他位置的數(shù)字,那有同學(xué)瞬間感覺(jué)有些燒腦了??

不過(guò)沒(méi)關(guān)系,我們慢慢來(lái)分析一下??

① 思路分析

  • 首先不去考慮第n位置,先去考慮某個(gè)特定的位置,假設(shè)我現(xiàn)在有個(gè)變量a為10,那么它的二進(jìn)制位即為00000000000000000000000000001010,那么此時(shí)我們先將其第三位置為1,要怎么去實(shí)現(xiàn)呢?
  • 首先就是要使用到我們上面學(xué)習(xí)過(guò)的按位或 | 運(yùn)算,將第三位按位或上一個(gè)1,那么這一位就變成了1,但是呢又不想讓其他位置發(fā)生變化,那此時(shí)就讓其他位按位或上一個(gè)0即可,若是那個(gè)位上為0,那么就是0,若是那個(gè)位上為1,那也為1,那也就是00000000000000000000000000000100,但是要如何去獲取到這個(gè)二進(jìn)制數(shù)呢,此時(shí)就又需要使用到我們上面講到過(guò)的一個(gè)操作符叫做左移<<那也就是將一個(gè)數(shù)擴(kuò)大兩倍,這里我們對(duì)1進(jìn)行操作,擴(kuò)大2倍就是2,再擴(kuò)大兩倍就是我們想要的4,即1 << 2
  • 具體的表達(dá)式應(yīng)該為:[a = a | 1 << 2]

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

  • 來(lái)看看運(yùn)行結(jié)果

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

  • 此時(shí)我們已經(jīng)完成了第一步,若是你想要置哪個(gè)位上的數(shù)為1的話,那就修改表達(dá)式的最后一個(gè)數(shù)字即可,但是呢這樣的話并沒(méi)有很大的通用性,需要每次運(yùn)行前做一個(gè)修改,此時(shí)就來(lái)實(shí)現(xiàn)題目中的需求
  • 可以再來(lái)修改一個(gè)位上的數(shù),若是我們要將第5位置為1的話,左移4位即可那也就是1 << 4,最后的結(jié)果就是26

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

  • 再來(lái)看看運(yùn)行結(jié)果

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】
② 規(guī)律總結(jié)

  • 從上述的兩個(gè)例子就可以找出規(guī)律
  • 若是要置【第3位】的數(shù)為1的話,使用數(shù)字1左移2位1 << 2;
  • 若是要置【第5位】的數(shù)為1的話,使用數(shù)字1左移4位1 << 4;
  • 若是要置【第n位】的數(shù)為1的話,使用數(shù)字1左移(n - 1)位1 << (n - 1);
  • 那么此時(shí)的話就可以將這個(gè)n作為我們自己輸入的一個(gè)變量,每次想要修改哪一個(gè)直接輸入即可
int main(void)
{
	int a = 10;
	int n = 0;

	scanf("%d", &n);
	a = a | 1 << (n - 1);
	//把變量a的第n為置1
	//000000000000000000001010
	//000000000000000000010000
//--------------------------------
	//000000000000000000001110
	printf("a = %d\n", a);
	return 0;
}

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】


【需求2】:將變量a的第n位置為0

實(shí)現(xiàn)了上面這個(gè)需求之后,便要去另一個(gè)需求,可以將一個(gè)二進(jìn)制數(shù)的某一位置為1,那能不能置為0呢? 我們來(lái)研究研究??

  • 要將一個(gè)二進(jìn)制位置為0的話就又需要使用到我們上面所學(xué)習(xí)過(guò)的按位與&,也就是將需要置0的那一位按位與上一個(gè)0即可,因?yàn)槿魏螖?shù)和0進(jìn)行與都為0,但是呢又不能使得其他二進(jìn)制位發(fā)生改變,那就要使其他二進(jìn)制位按位與上一個(gè)1即可,若是那個(gè)位上為0,那么就是0,若是那個(gè)位上為1,那也為1,那此時(shí)我們?cè)賹?duì)剛才的第三位進(jìn)行一個(gè)按位與即11111111111111111111111111111011
  • 可是要怎么產(chǎn)生這些個(gè)二進(jìn)制位呢,還記得剛才使用的1 << 2嗎,即00000000000000000000000000000100,那其實(shí)仔細(xì)觀察就可以看出這兩個(gè)二進(jìn)制位其實(shí)每個(gè)位呈現(xiàn)的都是一個(gè)相反的趨勢(shì),那么我們?cè)谏厦媸褂玫降奈徊僮鞣心膫€(gè)具有取反的功能呢?其實(shí)說(shuō)得很明顯了,就是按位取反,那其實(shí)只需要將剛才求出的那個(gè)表達(dá)式外層再加上一個(gè)按位取反符就可以了
  • 具體的表達(dá)式應(yīng)該為:[a = a & ~(1 << (n - 1))]

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

  • 再來(lái)看看運(yùn)行結(jié)果

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】
給出整體代碼?

int main(void)
{
	int a = 10;
	int n = 0;

	scanf("%d", &n);
	a = a | 1 << (n - 1);
	//把變量a的第n為置1
	//00000000000000000000000000001010
	//00000000000000000000000000000100
//--------------------------------
	//00000000000000000000000000011010
	printf("置1:a = %d\n", a);

	a = a & ~(1 << (n - 1));
	//把變量a的第n為置0
	//00000000000000000000000000001110
	//11111111111111111111111111111011
//--------------------------------
	//00000000000000000000000000001010
	printf("置0:a = %d\n", a);
	return 0;
}

從上述這個(gè)案例來(lái)看,真的可以說(shuō)是淋漓盡致地展現(xiàn)了位運(yùn)算的奇妙之處??

四、賦值操作符

  • 賦值操作符是一個(gè)很棒的操作符,他可以讓你得到一個(gè)你之前不滿意的值。也就是你可以給自己重新賦值
int weight = 120;	//體重
weight = 89;		//不滿意就賦值
double salary = 10000.0;
salary = 20000.0;	//使用賦值操作符賦值
  • 不僅如此,賦值操作符還可以進(jìn)行連續(xù)使用
int b = a += 10;

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

  • 但是對(duì)于上面這樣的代碼其實(shí)是不太好的,將所有的運(yùn)算都堆積堆積在一起,就無(wú)法調(diào)試了,一個(gè)F10就進(jìn)入了下一行代碼
  • 但如果寫成像下面這樣的話就顯得非常清爽而且易于調(diào)試
a += 10;
b = a;

復(fù)合賦值符

  • 對(duì)于賦值操作符來(lái)說(shuō),還可以和其他操作符進(jìn)行一個(gè)復(fù)合的操作
  • 例如:【+=】、【-=】、【*=】、【/=】、【%=】、【>>=】、【<<=】、【^=】等等。下面舉出兩個(gè)例子??

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】
C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

五、單目操作符

1、單目操作符介紹

首先來(lái)瀏覽一下所有的單目操作符??

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

2、【!】邏輯反操作

  • 對(duì)于邏輯取反操作符來(lái)說(shuō),就是[真變假,假變真]
int main(void)
{
	int flag = 0;
	if (!flag)
	{
		printf("haha\n");
	}
	return 0;
}
  • 具體的用法就是像上面這樣,若是某個(gè)變量為假的時(shí)候,就做一些特殊的操作,當(dāng)然你也可以寫成if(flag == 0),不過(guò)這樣看起來(lái)就不像是一個(gè)真假的判斷
  • 對(duì)于這個(gè)操作符其實(shí)我們?cè)诤竺鏀?shù)據(jù)結(jié)構(gòu)的二叉樹(shù)中也蠻常用的,因?yàn)樵诙鏄?shù)進(jìn)行向下遞歸的時(shí)候需要有遞歸出口,那就是當(dāng)前傳進(jìn)來(lái)的根節(jié)點(diǎn)是否為NULL,就可以寫成if(!root)或者是if(root == NULL),當(dāng)然如果你聽(tīng)不懂的話可以看看我的二叉樹(shù)文章,后續(xù)對(duì)應(yīng)地去學(xué)習(xí)一下即可,這里想到里我就順便說(shuō)一下

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

3、【&】和【*】

  • 對(duì)于【&】來(lái)說(shuō)叫做取地址操作符,可以獲取一個(gè)變量在內(nèi)存中的地址。就如下面這樣去取到這兩個(gè)整形變量和字符型變量的地址

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

  • 當(dāng)然我現(xiàn)在覺(jué)得這樣去取地址打印查看太費(fèi)時(shí)間了,那我們就可以將這塊地址存放到一個(gè)指針中去,在初始C語(yǔ)言的時(shí)候我有說(shuō)到過(guò)一個(gè)對(duì)于地址而言其實(shí)就是一個(gè)指針,所以我們將其給到一個(gè)指針變量是完全沒(méi)有問(wèn)題的,只是我們廣義上說(shuō)的指針接收地址

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

  • 再帶大家稍微回顧一下指針的有關(guān)知識(shí),對(duì)于pa前面的[*]而言,指的就是此為一個(gè)指針變量,而[*]前面的[int]表示這個(gè)指針變量所指向的是一個(gè)整型的地址。那當(dāng)前這個(gè)指針的名字是什么呢,就是pa,而不是*pa
  • 那這個(gè)時(shí)候我要獲取到這個(gè)指針?biāo)赶虻牡刂分械膶?duì)象要怎么做呢,那就是要用到【*】這個(gè)解引用操作符

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

  • 若是可以獲取到這個(gè)地址中的對(duì)象,那我們就可以對(duì)其進(jìn)行一個(gè)修改了,即*pa = 20
  • 但若是你沒(méi)有使用[*]解引用操作符獲取到這個(gè)對(duì)象就為他賦值,那其實(shí)編譯器會(huì)會(huì)報(bào)出一個(gè)Warning說(shuō)是等號(hào)兩邊的類型級(jí)別不同,這其實(shí)就是講一個(gè)整型的變量強(qiáng)制給到一個(gè)指針變量,才會(huì)出現(xiàn)的類型異常問(wèn)題

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

  • 那其實(shí)這一步操作就是在使這個(gè)指針變量重新指向一塊新的地址,即00000014,轉(zhuǎn)換為十進(jìn)制也就是【20】

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

  • 再來(lái)拓展一塊有關(guān)野指針的內(nèi)容,因?yàn)檫@一個(gè)只有相關(guān)很危險(xiǎn)?的東西,也是很多初學(xué)者容易犯的
*(int*)0x0012f40 = 100
  • 對(duì)于上面這個(gè)語(yǔ)句,首先我捏造了一個(gè)十六進(jìn)制的整數(shù),然后將其強(qiáng)制化為一個(gè)整型地址,在前面加上一個(gè)[*]解引用操作符,此時(shí)我就可以去修改這個(gè)地址中存放著的對(duì)象了,將其對(duì)象的值修改為100,然后可以看到去編譯的時(shí)候是沒(méi)有問(wèn)題的

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

  • 但是一運(yùn)行起來(lái)可以看到發(fā)生了寫入異常,這其實(shí)就是野指針,因?yàn)檫@個(gè)十六進(jìn)制的數(shù)值,這個(gè)地址是我隨手捏造出來(lái)的,操作系統(tǒng)并沒(méi)有為其分配內(nèi)存,因此這是一塊隨機(jī)的地址值,是不確定的,若是隨便去訪問(wèn)這塊地址的話就會(huì)造成問(wèn)題
  • 這其實(shí)和我們?cè)卺尫诺粢粔K申請(qǐng)的地址時(shí)然后沒(méi)有將其置為NULL是一個(gè)道理,若是你有一個(gè)指針去訪問(wèn)這塊隨機(jī)的地址,那么你的這個(gè)指針就叫做[野指針]

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

聽(tīng)完這些,相信你一定回憶起了一些有關(guān)指針和地址的知識(shí)點(diǎn)

4、【-】和【+】

對(duì)于【-】和【+】這個(gè)兩個(gè)操作符并不常用,其實(shí)它們不能完全說(shuō)只是單目操作符,因?yàn)樵谔囟ǖ膱?chǎng)景下它們也可以算是一個(gè)雙目操作符,例如:-6的話就只一個(gè)單目操作符,8 - 3的話就是第一個(gè)雙目操作符,【+】的話也是同理,不做贅述

5、sizeof [?]

然后我們?cè)賮?lái)說(shuō)說(shuō)一個(gè)操作符,叫做sizeof,你沒(méi)聽(tīng)錯(cuò),那就是個(gè)操作符??

① 寫在前面

  • 對(duì)于sizeof來(lái)說(shuō),是用來(lái)計(jì)算操作數(shù)的類型長(zhǎng)度,它以字節(jié)為單位。在sizeof后跟一個(gè)小括號(hào)(),里面就是你要計(jì)算的數(shù)據(jù)類型,但是很多同學(xué)看到這個(gè)小括號(hào)()的時(shí)候很多同學(xué)就會(huì)認(rèn)為這是一個(gè)函數(shù),它確實(shí)和函數(shù)的樣子很類似。
  • 對(duì)于函數(shù),它后面的這個(gè)小括號(hào)叫做函數(shù)調(diào)用操作符,在后面我也會(huì)說(shuō)到,可是對(duì)于sizeof后面的這個(gè)()來(lái)說(shuō)卻不一樣,這只是一種語(yǔ)法規(guī)定罷了,你只需要記住這么去用,而且不要把它當(dāng)成函數(shù)就行??

  • 使用sizeof()可以去計(jì)算很多數(shù)據(jù)類型的長(zhǎng)度,例如一個(gè)整型變量、一個(gè)指針、一個(gè)數(shù)組元素大小、一整個(gè)數(shù)組等等。。。
  • 對(duì)于sizeof()而言有其特定的返回值打印格式【%zu
int a = 10;
int* p;
int arr[10];

printf("%zu\n", sizeof(a));			//int 4
printf("%zu\n", sizeof(p));			//int 4
printf("%zu\n", sizeof(arr));		//特殊,計(jì)算的是整個(gè)數(shù)組的大小
printf("%zu\n", sizeof(arr[0]));	//int [10] 40
printf("%zu\n", sizeof(arr[10]));	//int 4

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

② sizeof后可省略()

  • 如何更加地去明確sizeof是一個(gè)操作符呢,那就是它后面的()其實(shí)是可以省略的。看到下面的代碼沒(méi)有語(yǔ)法方面的報(bào)錯(cuò)。因?yàn)槲覀兤匠K?jiàn)的操作符和操作數(shù)結(jié)合的時(shí)候都不會(huì)看到(),這其實(shí)就更有力地說(shuō)明了它是一個(gè)操作符

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

③ sizeof()內(nèi)部表達(dá)式不參與計(jì)算

  • 接著來(lái)看到下面這段代碼,可以看到我在sizeof()內(nèi)部寫了一個(gè)表達(dá)式,這其實(shí)也是合法的,大家來(lái)猜一猜輸出的結(jié)果是多少
int main(void)
{
	short s = 10;
	int a = 2;
	
	printf("%d\n", sizeof(s = a + 2));
	printf("%d\n", s);

	return 0;
}

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

  • 看到上面的這個(gè)結(jié)果你可能會(huì)震驚(○′?д?)?讓我猜猜看你算出來(lái)的答案是不是【4】和【7】呢,亦或是其他的答案,雖然sizeof()內(nèi)部是可以放表達(dá)式的,但是呢這個(gè)表達(dá)式是不參與運(yùn)算的
  • 我們?cè)诳催@個(gè)sizeof()最后的結(jié)果時(shí)其實(shí)只需要看這個(gè)s即可,短整型為2個(gè)字節(jié),那如果這個(gè)表達(dá)式不計(jì)算的話s的值也就不會(huì)發(fā)生變化了,所以最后打印出來(lái)是10
  • 那有同學(xué)可能會(huì)疑惑為什么這個(gè)表達(dá)式不參與運(yùn)算呢?又是語(yǔ)法規(guī)定嗎?
    • 答:一方面是這樣,但是在內(nèi)存中看來(lái),在運(yùn)行階段的時(shí)候,這個(gè)表達(dá)式其實(shí)早就已經(jīng)不在了,因?yàn)樗诰幾g階段的時(shí)候就會(huì)替換成了short

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

  • 如果想了解為何在編譯階段會(huì)發(fā)生替換可以看看我的這篇文章 ——> C生萬(wàn)物 | 詳解程序環(huán)境和預(yù)處理【展示程序編譯+鏈接全過(guò)程】

  • 不過(guò)這里還要給讀者補(bǔ)充的一點(diǎn)是有關(guān)數(shù)據(jù)截?cái)?/code>這個(gè)小知識(shí),若是我們不將這個(gè)表達(dá)式放到sizeof()中去,而是拿到外面來(lái)計(jì)算,那么最后s的結(jié)果還是會(huì)發(fā)生改變的,不過(guò)可以看到對(duì)于a + 5的結(jié)果它是一個(gè)整型,占4個(gè)字節(jié),但是變量s呢它是一個(gè)短整型,占2個(gè)字節(jié),若是 強(qiáng)行將4個(gè)字節(jié)的數(shù)據(jù)放到2個(gè)字節(jié)中去,其實(shí)就會(huì)發(fā)生一個(gè)【數(shù)據(jù)截?cái)唷窟@個(gè)一個(gè)現(xiàn)象

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

  • 下面其實(shí)就是在內(nèi)存中的一個(gè)截?cái)嗖僮鳎瑥?qiáng)行將一個(gè)整型變量給到一個(gè)短整型都會(huì)造成這樣的情況,所以我們?cè)谶M(jìn)行賦值的時(shí)候要看清楚數(shù)據(jù)類型
    C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

④ sizeof() 與數(shù)組

  • 最后再來(lái)講講sizeof()和數(shù)組之間的運(yùn)算,首先看看下面這段代碼
#include <stdio.h>
void test1(int arr[])
{
	printf("%d\n", sizeof(arr));
}

void test2(char ch[])
{
	printf("%d\n", sizeof(ch));
}

int main()
{
	int arr[10] = {0};
	char ch[10] = {0};
	printf("%d\n", sizeof(arr));
	printf("%d\n", sizeof(ch));
	test1(arr);
	test2(ch);
	return 0;
}
  • 答案是下面這4個(gè),你猜對(duì)了嗎,前面3個(gè)相信你一定沒(méi)問(wèn)題,但是對(duì)于最后一個(gè)我猜一猜是不是算成【1】了 (^ _^)

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

  • 正好通過(guò)這一塊我們?cè)賮?lái)回顧一下有關(guān)數(shù)組名的知識(shí)
  • 對(duì)于數(shù)組名,一般來(lái)說(shuō)指的都是首元素地址
  • sizeof(數(shù)組名) —— 計(jì)算的是整個(gè)數(shù)組的大小【特殊情況1】
  • &數(shù)組名 —— 獲取整個(gè)數(shù)組的地址【特殊情況2】
  • 有了這些知識(shí),再來(lái)分析一下上面的這段代碼,首先第一個(gè)【sizeof(arr)】,arr表示數(shù)組名,那么計(jì)算的就是整個(gè)數(shù)組的大小,這是一個(gè)整型數(shù)組,數(shù)組中有10個(gè)元素,每個(gè)元素4個(gè)字節(jié),那么整個(gè)數(shù)組的大小就是40個(gè)字節(jié)
  • 對(duì)于【sizeof(ch)】而言也是同理,這是一個(gè)字符型數(shù)組,數(shù)組中有10個(gè)元素,每個(gè)元素1個(gè)字節(jié),那么整個(gè)數(shù)組的大小就是10個(gè)字節(jié)
  • 接下去就是將數(shù)組名傳入函數(shù)中,除了兩種特殊的情況而言,數(shù)組名就相當(dāng)于是首元素地址,然后函數(shù)形參中便是指針進(jìn)行接受,那對(duì)于一個(gè)指針而言,無(wú)論它是【整型指針】、【字符型指針】【浮點(diǎn)型指針】均為4個(gè)字節(jié),當(dāng)然這是在32為系統(tǒng)下,若是在64位系統(tǒng)下就為8個(gè)字節(jié),這其實(shí)取決于計(jì)算機(jī)內(nèi)存中地址總線的長(zhǎng)度,有興趣可以去了解一下
  • 那既然上面說(shuō)到一個(gè)指針均為4個(gè)字節(jié),就可以得出為什么最后一個(gè)sizeof(ch)為4了,這也只是在求一個(gè)指針的大小,不要和字符串?dāng)?shù)據(jù)所占字節(jié)數(shù)混淆了

以上便是對(duì)于sizeof()這個(gè)操作符而言要介紹的所有內(nèi)容,希望讀者能夠理解??

6、【++】和【- -】

首先來(lái)看看前置++和后置++

int a = 10;
int b = ++a;
//a = a + 1; b = a;

printf("a = %d, b = %d\n", a, b);
int a = 10;
int b = a++;
//b = a; a = a + 1; 

printf("a = %d, b = %d\n", a, b);
  • 可以看到,對(duì)于這里的b = ++a相當(dāng)于就是先讓a++,然后再把a(bǔ)的值給到b
  • 可以看到,對(duì)于這里的b = a++相當(dāng)于就是先把a(bǔ)的值給到b,然后再讓a++

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】
C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】


接著再來(lái)看看前置- -和后置- -

int a = 10;
int b = --a;
//a = a - 1; b = a;

printf("a = %d, b = %d\n", a, b);
int a = 10;
int b = a--;
//b = a; a = a - 1; 

printf("a = %d, b = %d\n", a, b);
  • 可以看到,對(duì)于這里的b = --a相當(dāng)于就是先讓a- -,然后再把a(bǔ)的值給到b
  • 可以看到,對(duì)于這里的b = a--相當(dāng)于就是先把a(bǔ)的值給到b,然后再讓a- -

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】
C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

7、強(qiáng)制類型轉(zhuǎn)換

最后的話再來(lái)說(shuō)一下強(qiáng)制類型轉(zhuǎn)換

  • 比方說(shuō)我這里將一個(gè)double類型的數(shù)據(jù)強(qiáng)制給到一個(gè)int類型的變量,就會(huì)出現(xiàn)一種叫做【精度丟失】的現(xiàn)象,若是想要強(qiáng)制給到一個(gè)整型的變量,那就要去做一個(gè)強(qiáng)制類型轉(zhuǎn)換

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

  • 可以看到這樣就不會(huì)出現(xiàn)問(wèn)題了,所以你想要把一個(gè)不同數(shù)據(jù)類型的值給到一個(gè)另一個(gè)數(shù)據(jù)類型的變量,就可以使用強(qiáng)制類型轉(zhuǎn)換
int a = (int)3.14;

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

六、關(guān)系操作符

  • 關(guān)系操作符主要有下面這些??
    【>】、【>=】、【<】、【<=】、【! =】、【==】
  • 對(duì)于這些操作符來(lái)說(shuō)大家平常在使用的時(shí)候也都會(huì)碰到過(guò),這里主要強(qiáng)調(diào)的一塊就是==,因?yàn)樗?jīng)常會(huì)和賦值操作符=混淆,其實(shí)也不能說(shuō)是混淆,應(yīng)該說(shuō)是【遺漏】,包括是很多資深的程序員在寫代碼判斷一個(gè)數(shù)是否等于某個(gè)值的時(shí)候都會(huì)犯這樣的錯(cuò)誤
    • 例如將a == 6寫成a = 6 ,若是將這個(gè)語(yǔ)句寫在if條件判斷里的話那么無(wú)論a的值為多少都會(huì)進(jìn)入這個(gè)條件分支,因?yàn)橘x值永遠(yuǎn)都是成立的,也就是為真
  • 所以我們平常在判斷的時(shí)候一般不寫a == 10,一般都寫成10 == a
    • 因?yàn)榍罢呷羰巧约恿艘粋€(gè)【=】的話編譯器是不會(huì)報(bào)出錯(cuò)誤的,那后面再調(diào)試的時(shí)候就會(huì)很麻煩
    • 可是若后者少加了一個(gè)【=】的話編譯器就會(huì)報(bào)出錯(cuò)誤,因?yàn)橐粋€(gè)變量是不可以賦值給到一個(gè)常量的,這就屬于語(yǔ)法方面的錯(cuò)誤了

對(duì)于==操作符還想再說(shuō)幾句的是我們有時(shí)候不僅僅會(huì)去比較某個(gè)數(shù)值,而是去比較兩個(gè)字符串的內(nèi)容是否相同或者是比較一些結(jié)構(gòu)體成員的變量,可是呢對(duì)于【==】操作符來(lái)說(shuō)是不具備那么強(qiáng)大的功能的,所以要用其他手段去實(shí)現(xiàn)

  • 對(duì)于兩個(gè)字符串的內(nèi)容,我后面在將字符串內(nèi)容的時(shí)候會(huì)說(shuō)到一個(gè)庫(kù)函數(shù)叫做strcmp,它是專門用來(lái)比較字符串內(nèi)容的,若是直接用==去比較的話不是比較的兩個(gè)字符串的內(nèi)容,而是比較的兩個(gè)字符串的首元素地址罷了
  • 對(duì)于結(jié)構(gòu)體成員的比較,也是有獨(dú)特的方法,不過(guò)對(duì)于普通的結(jié)構(gòu)體成員,整數(shù)、浮點(diǎn)數(shù)就直接用【==】比較也是可以的,字符串的話用上面的strcmp,而對(duì)于定義出來(lái)的整個(gè)結(jié)構(gòu)體成員對(duì)象的內(nèi)容就不好比較了,之后我們?cè)趯W(xué)習(xí)了C++之后就知道有個(gè)東西叫做[仿函數(shù)],可以比較自定義的數(shù)據(jù)類型

七、邏輯操作符

邏輯操作符很好記,就兩個(gè),和我們前面學(xué)過(guò)的位操作符中的按位與&按位或|很像

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

  • 要區(qū)分邏輯與按位與
  • 要區(qū)分邏輯或按位或

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

  • 可以看到對(duì)于邏輯與邏輯或來(lái)說(shuō)它們最終的結(jié)果只會(huì)有兩種,那就是【1】和【0】;但是對(duì)于位操作符來(lái)說(shuō)是千變?nèi)f化的,因?yàn)閮蓚€(gè)數(shù)進(jìn)行位運(yùn)算取決的是32個(gè)二進(jìn)制位上的0和1

邏輯與和或的特點(diǎn):
?【邏輯與&&】:表達(dá)式兩邊均為真才是真,若第一個(gè)為假,那么整個(gè)表達(dá)式為假,第二個(gè)表達(dá)式不參與運(yùn)算
?【邏輯或 ||】:表達(dá)式兩邊有一邊為真即為真,若第一個(gè)為真,那么整個(gè)表達(dá)式為真,第二個(gè)表達(dá)式不參與運(yùn)算

一道【奇虎360】筆試題?

下面是一道【奇虎360】公司的校招筆試題,請(qǐng)問(wèn)程序輸出的結(jié)果是什么?

#include <stdio.h>
int main()
{
    int i = 0, a = 0, b = 2, c = 3, d = 4;
    i = a++ && ++b && d++;
    
    printf("a = %d\nb = %d\nc = %d\nd = %d\n", a, b, c, d);
    printf("------\n");
    printf("i = %d\n", i);
    return 0;
}
  • 這道題考察的就是你對(duì)于[邏輯操作符][單目操作符]的綜合運(yùn)用能力
  • 下面是最終的結(jié)果,你算對(duì)了嗎?

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

  • 來(lái)分析一下其實(shí)就可以看出 ,因?yàn)閍一開(kāi)始為0,所以前兩個(gè)邏輯與之后的結(jié)果一定為0,那么除了第一個(gè)a++表達(dá)式需要運(yùn)算之外后面的表達(dá)式都不會(huì)參與運(yùn)算,因此最后的結(jié)果為1 2 3 4,【i】的結(jié)果即為0
  • 這里要注意的一點(diǎn)就是邏輯與前面一個(gè)表達(dá)式已為假那么第二個(gè)表達(dá)式是不會(huì)參與運(yùn)算的
    C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

現(xiàn)在我將這個(gè)題目做幾個(gè)變形,看看讀者是否具有舉一反三的能力??

題目變形①

  • 看到我將a的初始值做了一個(gè)修改,變?yōu)?,那么請(qǐng)問(wèn)結(jié)果是多少呢?
int i = 0, a = 1, b = 2, c = 3, d = 4;
i = a++ && ++b && d++;

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

  • 來(lái)分析一下,初始化a為1,b為2,那在a++++b之后與運(yùn)算的表達(dá)式即為1 && 3,運(yùn)算之后的結(jié)果即為1,然后這個(gè)1再和d++去進(jìn)行一個(gè)運(yùn)算便可以得出最后的結(jié)果為【1】,那么a b c d 最后的結(jié)果即為2 3 3 5

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】


題目變形②

  • 既然學(xué)習(xí)了邏輯與,那邏輯或也少不了,接下去來(lái)練練邏輯或的用法吧
int i = 0, a = 0, b = 2, c = 3, d = 4;
i = a++ || ++b || d++;

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

  • 這里要注意的一點(diǎn)就是邏輯或前面一個(gè)表達(dá)式已為真那么第二個(gè)表達(dá)式是不會(huì)參與運(yùn)算的
  • 因此最后的結(jié)果即為1 3 3 4,【i】的值為1
    C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

題目變形③

  • 將這個(gè)a改為1再來(lái)看看最后輸出的結(jié)果為多少?
int i = 0, a = 1, b = 2, c = 3, d = 4;
i = a++ || ++b || d++;

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

  • 同理,本次的修改也可以看出邏輯或的特性,之后a++參與了運(yùn)算,因?yàn)樗粸?,那么后面都不會(huì)參與運(yùn)算了,最后的a b c d結(jié)果即為2 2 3 4
    C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

通過(guò)這道奇虎360公司的筆試題以及舉一反三的練習(xí),相信你對(duì)邏輯操作符一定有了自己的理解??

八、條件操作符

接下去我們來(lái)看看條件操作符,不過(guò)一般我們都將其叫做條件表達(dá)式(三目操作符)

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

  • 來(lái)看看下面這段代碼,一段很簡(jiǎn)答的邏輯判斷,但是呢你是否可以發(fā)現(xiàn)經(jīng)過(guò)if分支的一個(gè)判斷之后顯得非常冗余,那這個(gè)時(shí)候其實(shí)就可以使用到我們本節(jié)所要將的條件操作符
int main(void)
{
	int a = 5;
	int b = 0;

	if (5 == a)
		b = 3;
	else
		b = -3;

	printf("a = %d\n", a);
	printf("b = %d\n", b);
	return 0;
}
  • 將整個(gè)if的分支判斷寫成這樣的一句代碼時(shí),就顯得非常簡(jiǎn)潔,但是可能不了解這個(gè)操作符的同學(xué)可能會(huì)看懵,不夠你現(xiàn)在學(xué)習(xí)了這個(gè)操作符之后一定是完全沒(méi)問(wèn)題的
  • 也就是當(dāng)條件成立的時(shí)候,執(zhí)行第一個(gè)表達(dá)式,當(dāng)條件不成立的時(shí)候,執(zhí)行第二個(gè)表達(dá)式。可以看出我寫了后面也可以是一個(gè)表達(dá)式??
b = (5 == a) ? 3 : -3;

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】


然后我們使用這個(gè)條件操作符來(lái)練習(xí)一下求解兩個(gè)數(shù)的較大值

int a = 5;
int b = 3;

int ret = (a > b) ? a : b;
printf("ret = %d\n", ret);

九、逗號(hào)表達(dá)式【生僻,需了解】

下面來(lái)說(shuō)說(shuō)有關(guān)逗號(hào)表達(dá)式的用法

【格式】:exp1, exp2, exp3, …expN

【運(yùn)算規(guī)則】:從左向右依次計(jì)算,整個(gè)表達(dá)式的結(jié)果是最后一個(gè)表達(dá)式的結(jié)果

  • 首先來(lái)看一下第一段代碼,請(qǐng)你計(jì)算一個(gè)
//代碼1
int a = 1;
int b = 2;
int c = (a > b, a = b + 10, a, b = a + 1);//逗號(hào)表達(dá)式
printf("c = %d\n", c);
  • 最后的結(jié)果是13,你算對(duì)了嗎?運(yùn)行結(jié)果就不展示了
  • 來(lái)分析一下,根據(jù)逗號(hào)表達(dá)式的運(yùn)算規(guī)則可以知道它是從左向右進(jìn)行計(jì)算的,最終結(jié)果取的是最后一個(gè)表達(dá)式的結(jié)果,那么根據(jù)前面的計(jì)算可以得知b = 12,那么最后再計(jì)算便是13

  • 再來(lái)看一句代碼,可以看到這不是一個(gè)結(jié)果的運(yùn)算,而是將逗號(hào)表達(dá)式放在一個(gè)if分支判斷中,可以看到最后一個(gè)逗號(hào)后面的表達(dá)式為d > 0,那此時(shí)我們就要去看看前面一些表達(dá)式的運(yùn)算會(huì)不會(huì)使得這個(gè)d變化,若不會(huì)那么這個(gè)if判斷其實(shí)就等價(jià)于if(d > 0)
//代碼2
if (a = b + 1, c = a / 2, d > 0)

  • 最后再來(lái)看看下面這段代碼,就是不斷地在計(jì)算一個(gè)a的值然后求和,若是a什么時(shí)候到0了,便跳出這個(gè)while()循環(huán),但是可以看到a = get_val() count_val(a)這兩個(gè)表達(dá)式在while()循環(huán)上面調(diào)用了一次,然后再while()循環(huán)中在調(diào)用,顯得就有些冗余了,那此時(shí)我們就可以使用【逗號(hào)表達(dá)式】去進(jìn)行一個(gè)優(yōu)化
//代碼3
a = get_val();
count_val(a);
while (a > 0)
{
 	//業(yè)務(wù)處理
    a = get_val();
    count_val(a);
}
  • 可以看到,通過(guò)逗號(hào)表達(dá)式的一個(gè)優(yōu)化,代碼看起來(lái)就顯得很簡(jiǎn)潔,當(dāng)while()循環(huán)一進(jìn)來(lái),就會(huì)執(zhí)行a = get_val(), count_val(a)這兩個(gè)表示,但是呢最后起作用的還是a > 0,前面兩個(gè)表達(dá)式只是有可能會(huì)使a的值發(fā)生一個(gè)變化罷了
while (a = get_val(), count_val(a), a > 0)
{
      //業(yè)務(wù)處理
}

十、下標(biāo)引用、函數(shù)調(diào)用和結(jié)構(gòu)成員

1、下標(biāo)引用操作符 [ ]

【操作數(shù)】:一個(gè)數(shù)組名 + 一個(gè)索引值

  • 這個(gè)操作符我們?cè)谥v數(shù)組的時(shí)候也有用到過(guò),可能我們大家在使用的時(shí)候都是arr[1],不過(guò)既然它一個(gè)操作符,那么對(duì)于操作數(shù)來(lái)說(shuō)其實(shí)沒(méi)有位置的一個(gè)限制,其實(shí)是可以寫成1[arr],這個(gè)語(yǔ)法也是支持的,訪問(wèn)的都是arr這個(gè)數(shù)組中的第一個(gè)元素
  • 我們可以到VS中來(lái)演示看看

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

  • 可以看出兩種語(yǔ)法都是可行的,這一點(diǎn)你了解了嗎??

2、函數(shù)調(diào)用操作符 ( )

??接受一個(gè)或者多個(gè)操作數(shù):第一個(gè)操作數(shù)是函數(shù)名,剩余的操作數(shù)就是傳遞給函數(shù)的參數(shù)

  • 對(duì)于函數(shù)來(lái)說(shuō)相信都不陌生,這里主要給讀者講講有關(guān)函數(shù)的操作符和操作數(shù)之間的關(guān)系,可以看到下面這段代碼,對(duì)于test1()來(lái)說(shuō)它的操作符為(),只有一個(gè)操作數(shù)就是函數(shù)名test1
  • 再看到test2("hello bit."),對(duì)于它來(lái)說(shuō)操作符也為(),操作數(shù)的話有兩個(gè),一個(gè)為函數(shù)名test1,另一個(gè)則為函數(shù)參數(shù)"hello bit."
void test1()
{
	printf("hehe\n");
}

void test2(const char* str)
{
	printf("%s\n", str);
}

int main(void)
{
	test1();				//實(shí)用()作為函數(shù)調(diào)用操作符。
	test2("hello bit.");	//實(shí)用()作為函數(shù)調(diào)用操作符。
	return 0;
}

3、結(jié)構(gòu)成員調(diào)用操作符 . ->

最后再來(lái)說(shuō)說(shuō)這個(gè)結(jié)構(gòu)成員調(diào)用操作符【.】和【->】

  • 首先看到下面聲明了一個(gè)結(jié)構(gòu)體,是一本書,結(jié)構(gòu)成員有作家價(jià)格。然后我聲明了一個(gè)結(jié)構(gòu)體成員,初始化了它的成員變量
typedef struct book {
	char writer[20];
	double price;
}st;

st s1 = { "羅曼·羅蘭", 50 };
  • 首先我使用.操作符先進(jìn)行訪問(wèn),可以看到獲取了這個(gè)成員所有的成員變量
int main(void)
{
	st s1 = { "羅曼·羅蘭", 50 };
	printf("name = %s\n", s1.writer);
	printf("price = %f\n",s1.price);  //結(jié)構(gòu)體變量.結(jié)構(gòu)體成員名
	return 0;
}

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】


  • 接下去我們?cè)賮?lái)嘗試一下->操作符進(jìn)行一個(gè)訪問(wèn),那么對(duì)于這個(gè)操作符在上面講到過(guò),那既然這樣的話我們就需要去定義一個(gè)指針去接收這個(gè)結(jié)構(gòu)體成員的地址,那么這個(gè)指針就叫做[結(jié)構(gòu)體指針]
  • 那我們使用這個(gè)指針變量解引用是不是取到了這個(gè)結(jié)構(gòu)體的值,此時(shí)就可以去訪問(wèn)這些結(jié)構(gòu)體成員了,如下所示??
st* ps = &s1;

printf("name = %s\n", (*ps).writer);
printf("price = %f\n", (*ps).price);
  • 那我們就用->操作符來(lái)試試吧
printf("name = %s\n", ps->writer);	//結(jié)構(gòu)體指針->結(jié)構(gòu)體成員名
printf("price = %f\n", ps->price);
  • 可以看到對(duì)于這三種形式都是可以訪問(wèn)到這個(gè)結(jié)構(gòu)體變量的成員

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

十一、表達(dá)式求值

1、隱式類型轉(zhuǎn)換【?整型提升?】

接下去要講的這一個(gè)隱式類型轉(zhuǎn)換,可以很好地解開(kāi)你對(duì)很多類型轉(zhuǎn)換的一些困惑

C的整型算術(shù)運(yùn)算總是至少以缺省整型類型的精度來(lái)進(jìn)行的
??為了獲得這個(gè)精度,表達(dá)式中的字符型短整型操作數(shù)在使用之前被轉(zhuǎn)換為普通整型,這種轉(zhuǎn)換稱為[整型提升]

① 整型提升的意義

??表達(dá)式的整型運(yùn)算要在CPU的相應(yīng)運(yùn)算器件內(nèi)執(zhí)行,CPU內(nèi)整型運(yùn)算器(ALU)的操作數(shù)的字節(jié)長(zhǎng)度一般就是int的字節(jié)長(zhǎng)度,同時(shí)也是CPU的通用寄存器的長(zhǎng)度。
??因此,即使兩個(gè)char類型的相加,在CPU執(zhí)行時(shí)實(shí)際上也要先轉(zhuǎn)換為CPU內(nèi)整型操作數(shù)的標(biāo)準(zhǔn)長(zhǎng)度
??通用CPU(general-purpose CPU)是難以直接實(shí)現(xiàn)兩個(gè)8比特字節(jié)直接相加運(yùn)算(雖然機(jī)器指令中可能有這種字節(jié)相加指令)。所以,表達(dá)式中各種長(zhǎng)度可能小于int長(zhǎng)度的整型值,都必須先轉(zhuǎn)換為intunsigned int,然后才能送入CPU去執(zhí)行運(yùn)算

通過(guò)上面的陳述,相信你對(duì)整型提升有了一個(gè)初步的概念,接下去我們來(lái)看看如何去進(jìn)行一個(gè)整型提升??

② 如何進(jìn)行整型提升

  • 整形提升是按照變量的數(shù)據(jù)類型的符號(hào)位來(lái)提升的

對(duì)于整型提升來(lái)說(shuō),整數(shù)和負(fù)數(shù)是不一樣的,首先我們來(lái)看看正數(shù)的整型提升

//正數(shù)的整形提升
char c1 = 1;
  • 首先先來(lái)寫出1的32個(gè)二進(jìn)制位00000000000000000000000000000001,然后將其轉(zhuǎn)換為原碼的形式,但是通過(guò)上面的學(xué)習(xí)我們可以知道對(duì)正數(shù)的原、反、補(bǔ)碼是相同的,因此這就是它在內(nèi)存中的形式
  • 但是可以看到現(xiàn)在要將這個(gè)整數(shù)1給到一個(gè)char類型的變量c2,此時(shí),此時(shí)就會(huì)發(fā)生一個(gè)【截?cái)唷康默F(xiàn)象,因?yàn)橐粋€(gè)字符型的數(shù)據(jù)在內(nèi)存中只占1個(gè)字節(jié),也就是8個(gè)比特位,所以在截?cái)嘀缶椭皇O?code>00000001
  • 接下去若是要去使用這個(gè)c1的話就會(huì)進(jìn)行一個(gè)整型提升,此時(shí)在八個(gè)比特位的首部填充24個(gè)符號(hào)位,以達(dá)到整型4個(gè)字節(jié)32個(gè)比特位在內(nèi)存中的要求,那么此時(shí)提升之后的結(jié)果便是00000000000000000000000000000001可以看出又回到了原來(lái)的1,不過(guò)若是你不去使用這個(gè)c1的話是不需要進(jìn)行整型提升的

接下去再來(lái)看看負(fù)數(shù)的整型提升

//負(fù)數(shù)的整形提升
char c2 = -1;
  • 那對(duì)于負(fù)數(shù)其實(shí)也是一樣,-1 在內(nèi)存中的32位二進(jìn)制補(bǔ)碼為11111111111111111111111111111111。同理,將其給到一個(gè)整型的變量之后就會(huì)發(fā)生截?cái)嗉礊?code>11111111
  • 那這個(gè)時(shí)候再進(jìn)行一個(gè)整型提升就和正數(shù)不一樣了,因?yàn)樨?fù)數(shù)的符號(hào)位為1,而整型提升在高位是要補(bǔ)充符號(hào)位,所以會(huì)在前頭加上24個(gè)1,那其實(shí)也就變回了和之前-1的補(bǔ)碼一般的樣子,為32個(gè)1

好,說(shuō)完了該如何去進(jìn)行整型提升之后我們就可以去代碼段中看看到底是如何進(jìn)行的

③ 實(shí)戰(zhàn)演練

首先來(lái)看第一個(gè),我們要去計(jì)算兩個(gè)整數(shù)的和,但是呢卻要放到char類型的變量中去,那會(huì)發(fā)生什么化學(xué)反應(yīng)呢??

int main(void)
{
	char a = 5;
	char b = 126;
	char c = a + b;
}
  • 根據(jù)上一小節(jié)的講解,相信你已經(jīng)知道編譯器第一步會(huì)做什么了,首先的話就是分別寫出這兩個(gè)整數(shù)的32個(gè)比特位,接著轉(zhuǎn)換為補(bǔ)碼的形式,正數(shù)三者均一致。然后因?yàn)橐o到一個(gè)char類型的變量,所以會(huì)進(jìn)行一個(gè)【截?cái)唷?/li>
00000000000000000000000000000101 - 5
——> 00000101 - 5【截?cái)唷?00000000000000000000000001111110 - 126
——> 01111110 - 126【截?cái)唷?
  • 接下去我們要開(kāi)始去使用到這兩個(gè)字符型的變量了,使用它們進(jìn)行一個(gè)加法運(yùn)算,那么此時(shí)就會(huì)發(fā)生一個(gè)[整型提升],在高位補(bǔ)充24個(gè)符號(hào)位之后就變成了下面這樣,然后便可以對(duì)它們?nèi)ミM(jìn)行一個(gè)運(yùn)算了
//到了內(nèi)存中開(kāi)始計(jì)算 —— 整型提升(正數(shù))
00000000000000000000000000000101 - 5
00000000000000000000000001111110 - 126
  • 那在運(yùn)算出來(lái)之后呢在計(jì)算機(jī)中是一個(gè)補(bǔ)碼的形式,輸出來(lái)便得是一個(gè)原碼的形式,由于正數(shù)三者是一致,所以不發(fā)生改變(一強(qiáng)調(diào)這點(diǎn)是因?yàn)橄胱屪x者搞懂每一步)其實(shí)這時(shí)可以看到運(yùn)算出來(lái)的數(shù)字是正確的,5 + 126 = 131
  • 可是呢可以看到左邊又是拿了一個(gè)char類型定義的變量在接受這個(gè)運(yùn)算后的結(jié)果,因此便又會(huì)發(fā)生一個(gè)【截?cái)唷?,就只剩?strong>1個(gè)字節(jié)8個(gè)比特位了
  • 那其實(shí)在這個(gè)地方如果我用一個(gè)整型變量去接收一下然后再用%d做一個(gè)打印,那么此時(shí)就會(huì)輸出正確的內(nèi)容131
00000000000000000000000010000011 - 131
10000011 - 131【截?cái)唷?

可是呢,我就是不用整形去接收,就是玩??用字符型去接受,然后再用%d去打?。ā爸饕€是為了加深知識(shí)點(diǎn)的靈活運(yùn)用”)

printf("c的整數(shù)打印形式為:%d\n", c);
  • 那在若是在這個(gè)時(shí)候又要去進(jìn)行打印的話,又要放到內(nèi)存里面去運(yùn)算了,調(diào)用這個(gè)printf()庫(kù)函數(shù)其實(shí)也算是一個(gè)運(yùn)算,也要放到內(nèi)存里面去,然后這個(gè)變量c又不是整型,所以此時(shí)呢就又會(huì)發(fā)生一個(gè)[整型提升]
  • 此時(shí)就需要去補(bǔ)充10000011前面的24個(gè)符號(hào)位了
//整型提升(負(fù)數(shù))
11111111111111111111111110000011 - 補(bǔ)碼
11111111111111111111111110000010 - 反碼
10000000000000000000000001111101 - 原碼
  • 然后變要將這個(gè)32個(gè)二進(jìn)制位以十進(jìn)制的形式打印出來(lái),可是計(jì)算機(jī)中的運(yùn)算是采取補(bǔ)碼的形式,打印輸出的話就要采取補(bǔ)碼的形式了,所以此時(shí)就需要將這個(gè)補(bǔ)碼轉(zhuǎn)化為原碼了,可以看到這是一個(gè)負(fù)數(shù)的補(bǔ)碼,所以轉(zhuǎn)化為原碼的時(shí)候要小心了,需要將補(bǔ)碼-1然后再除符號(hào)位外均做取反
  • 此時(shí)再去轉(zhuǎn)化為十進(jìn)制的形式輸出便是-125,我們來(lái)看看結(jié)果【全體起立??】

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】


接下去再來(lái)看看第二個(gè)栗子??

  • 上面呢我們只說(shuō)到了字符類型的整型提升,下面呢我們?cè)賮?lái)看看短整型,它們都是屬于整型數(shù)據(jù)類型的一種
  • 可以看到定義了三個(gè)變量,分別是字符型、短整型、整型,然后初始化了一個(gè)十六進(jìn)制的數(shù)據(jù),那我們可以將其轉(zhuǎn)換為二進(jìn)制的形式便為10110110,那其實(shí)到這里我就已經(jīng)可以看出答案是多少了,只有最后一個(gè)if語(yǔ)句會(huì)進(jìn)去,其余的都不成立
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生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

  • 好,來(lái)解釋一下為什么我一眼就可以看出最后的結(jié)果是多少,并不是因?yàn)槲抑澜Y(jié)果,而是我看到了這個(gè)十六進(jìn)制的b,因?yàn)樗亩M(jìn)制為1011,可以看到首尾是為0,那么當(dāng)這個(gè)變量a參與運(yùn)算的時(shí)候就會(huì)發(fā)生一個(gè)[整型提升],在上面我說(shuō)到過(guò)對(duì)于負(fù)數(shù)的整型提升和正數(shù)不一樣,填充符號(hào)位后均為1,那么再轉(zhuǎn)化為原碼從計(jì)算機(jī)輸出之后就一定不會(huì)是原來(lái)的值了,會(huì)發(fā)生一個(gè)改變??
  • 對(duì)于char ashort b它們均不是一個(gè)整型int類型的數(shù)據(jù),所以都會(huì)發(fā)生一個(gè)[整型提升],不過(guò)int c它就是一個(gè)整型的變量,所以是不會(huì)發(fā)生變化的

通過(guò)這個(gè)例子相信你對(duì)整型提升一定有了更加深刻的理解


最后一個(gè)小案例我們和sizeof做一個(gè)結(jié)合,順便再回顧一下前面的知識(shí)點(diǎn)??

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

	return 0;
}

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

  • 通過(guò)運(yùn)行結(jié)果可以看到,有三個(gè)結(jié)果發(fā)生了整型提升,首先對(duì)于sizeof(c)很明確,計(jì)算的就是char這個(gè)數(shù)據(jù)類型的字節(jié)長(zhǎng)度,也就是1,可以對(duì)于下三個(gè)結(jié)果為什么會(huì)發(fā)生整型提升呢?我們來(lái)分析一下??
  • 對(duì)于c + 1來(lái)說(shuō)它是一個(gè)表達(dá)式,上面說(shuō)到過(guò)若是一個(gè)char類型或者是short類型定義的變量參與了運(yùn)算,那在內(nèi)存中就會(huì)發(fā)生一個(gè)整型提升,那如果這是一個(gè)表達(dá)式的話也就相當(dāng)于是參與了運(yùn)算,整型提升后變?yōu)?個(gè)字節(jié),具體細(xì)節(jié)不做展開(kāi)
  • 那對(duì)于+c-c來(lái)說(shuō)就是我們前面說(shuō)到過(guò)的單目操作符中的+-操作符,和一個(gè)操作數(shù)結(jié)合也可以說(shuō)它是一個(gè)表達(dá)式,那么同理也會(huì)進(jìn)行一個(gè)整型提升

但是我再將它們變個(gè)形卻又不會(huì)發(fā)生【整型提升】了,一起來(lái)看看??

char c = 1;
printf("%u\n", sizeof(c + 1));
printf("%u\n", sizeof(+c));

printf("-------------------\n");
printf("%u\n", sizeof(c = c + 1));
printf("%u\n", sizeof(++c));

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

  • 可以看到,若是將c + 1改換成了c = c + 1,就不會(huì)發(fā)生整型提升了,這是為什么呢?因?yàn)閷?duì)于c + 1這個(gè)表達(dá)式來(lái)說(shuō)確實(shí)會(huì)發(fā)生整型提升,但是呢我又將這個(gè)表達(dá)式計(jì)算后的結(jié)果放到c里面去,還記得我在講述【sizeof()】的時(shí)候說(shuō)到它里面的表達(dá)式是不會(huì)運(yùn)算的嗎,所以整個(gè)表達(dá)式的結(jié)果其實(shí)就是sizeof(c)的結(jié)果,和上面所列出的第一個(gè)是一樣的
  • 再來(lái)看看這個(gè)++c,那又有同學(xué)會(huì)產(chǎn)生疑惑,為何+c會(huì)發(fā)生整型提升,但是++c卻不會(huì)呢,其實(shí)對(duì)于++c來(lái)說(shuō)就等價(jià)于c = c + 1,那其沒(méi)有發(fā)生整型提升的原因相信你已經(jīng)清楚了

以上就是有關(guān)【整型提升】要介紹的所有內(nèi)容,看完這些相信你對(duì)計(jì)算機(jī)內(nèi)部隱式類型轉(zhuǎn)換一定有了一個(gè)深刻的了解??

2、算術(shù)轉(zhuǎn)換

如果某個(gè)操作符的各個(gè)操作數(shù)屬于不同的類型,那么除非其中一個(gè)操作數(shù)的轉(zhuǎn)換為另一個(gè)操作數(shù)的類
型,否則操作就無(wú)法進(jìn)行。下面的層次體系稱為【尋常算術(shù)轉(zhuǎn)換】

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

  • 其實(shí)很好理解。如果某個(gè)操作數(shù)的類型在上面這個(gè)列表中排名較低,那么首先要轉(zhuǎn)換為另外一個(gè)操作數(shù)的類型后執(zhí)行運(yùn)算?!九琶麖纳厦孀罡?,下面最低】
  • 例如intunsigned int一起進(jìn)行算術(shù)運(yùn)算的時(shí)候這個(gè)前者就要轉(zhuǎn)換為后者的類型
  • 例如long intlong double一起進(jìn)行算術(shù)運(yùn)算的時(shí)候這個(gè)前者就要轉(zhuǎn)換為后者的類型
  • 那其實(shí)可以看出,在char和short面前稱霸的int如今淪落為了小弟??

【警告】:
但是算術(shù)轉(zhuǎn)換要合理,要不然會(huì)有一些潛在的問(wèn)題

int main(void)
{
	float f = 3.14;
	int num = f;//隱式轉(zhuǎn)換,會(huì)有精度丟失

	printf("%d\n", num);
	return 0;
}
  • 可以看到,在編譯的階段就出現(xiàn)了一個(gè)精度丟失的Warning?

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

3、操作符的屬性【附優(yōu)先級(jí)列表】

復(fù)雜表達(dá)式的求值有三個(gè)影響的因素

  1. 操作符的優(yōu)先級(jí)
  2. 操作符的結(jié)合性
  3. 是否控制求值順序
  • 兩個(gè)相鄰的操作符先執(zhí)行哪個(gè)?取決于他們的優(yōu)先級(jí)。如果兩者的優(yōu)先級(jí)相同,取決于他們的結(jié)合性

下面有一張關(guān)于操作符優(yōu)先級(jí)的列表,可以保存一份日常的參考

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

??聊聊問(wèn)題表達(dá)式

表達(dá)式的求值部分由操作符的優(yōu)先級(jí)決定,優(yōu)先級(jí)只能決定先算誰(shuí),但是哪個(gè)表達(dá)式先調(diào)用要取決于編譯器

  • 對(duì)于有些表達(dá)式而言,其實(shí)在不同的編譯器上所呈現(xiàn)的結(jié)果是不同的,我們將其稱作為【問(wèn)題表達(dá)式】

① 問(wèn)題表達(dá)式1

a*b + c*d + e*f
  • 來(lái)看上面這段代碼,通過(guò)上面的優(yōu)先級(jí)列表可以看出[*]的優(yōu)先級(jí)一定是比[+]要來(lái)得高,因此可以保證[*]兩端的數(shù)字先進(jìn)行運(yùn)算,但是卻不能保證第三個(gè)*比第一個(gè)+早執(zhí)行

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】
C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

  • 可以看到,即使是存在操作符的優(yōu)先級(jí),但是這個(gè)表達(dá)式的計(jì)算還是存在一個(gè)歧義

② 問(wèn)題表達(dá)式2

  • 繼續(xù)來(lái)看下一個(gè)問(wèn)題表達(dá)式
//表達(dá)式2
c + --c;
  • 雖然對(duì)于這個(gè)[--]操作符來(lái)說(shuō)比[+]操作符的優(yōu)先級(jí)來(lái)得高,但是呢我們卻不知道在編譯器運(yùn)算的時(shí)候這個(gè)【c】是什么時(shí)候準(zhǔn)備好
  • 這樣說(shuō)你可能不是很理解,可以看看我的這篇文章 ——> 反匯編深挖【函數(shù)棧幀】的創(chuàng)建和銷毀。通過(guò)這篇文章你一定可以看出對(duì)于遍歷的創(chuàng)建時(shí)機(jī)其實(shí)在編譯器內(nèi)部是存在一個(gè)時(shí)間的先后順序的,你并不知道它何時(shí)會(huì)壓棧
    C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】
  • 通過(guò)畫圖分析我們也可以看出若是前面的這個(gè)c先入棧了,先準(zhǔn)備了,那么后的--c就是根據(jù)這個(gè)【2】來(lái)運(yùn)算;可若是這個(gè)--c先執(zhí)行的話,后面再去加上這個(gè)c結(jié)果就不一樣了。因此也將其成為問(wèn)題表達(dá)式

③ 問(wèn)題表達(dá)式3

  • 同樣,對(duì)于下面這段代碼,也是存在很大的爭(zhēng)議,特別是對(duì)于++--混搭的這種表達(dá)式尤其嚴(yán)重,你可以去不同的編譯器上運(yùn)行看看,結(jié)果都是不一樣的【這種代碼不要寫,練練思維就行】
//代碼3-非法表達(dá)式
int main()
{
	int i = 10;
	i = i-- - --i * ( i = -3 ) * i++ + ++i;
	printf("i = %d\n", i);
	return 0;
}
  • 下面是我在不同的編譯器上運(yùn)行出來(lái)的結(jié)果,可見(jiàn)這個(gè)表達(dá)式問(wèn)題有多大!
編譯器
- 128 Tandy 6000 Xenix 3.2
- 95 Think C 5.02(Macintosh)
- 86 IBM PowerPC AIX 3.2.5
- 85 Sun Sparc cc(K&C編譯器)
- 63 gcc,HP_UX 9.0,Power C 2.0.0
4 Sun Sparc acc(K&C編譯器)
21 Turbo C/C++ 4.5
22 FreeBSD 2.1 R
30 Dec Alpha OSF1 2.0
36 TDec VAX/VMS
42 Microsoft C 5.1

④ 問(wèn)題表達(dá)式4

  • 繼續(xù)來(lái)看下面是一個(gè)有關(guān)函數(shù)調(diào)用的問(wèn)題表達(dá)式,函數(shù)內(nèi)部聲明了一個(gè)靜態(tài)的整型變量count,我們知道對(duì)于靜態(tài)變量是存放在內(nèi)存中的【靜態(tài)區(qū)】,每一次運(yùn)算都是在上一次的運(yùn)算的結(jié)果后進(jìn)行一個(gè)累加
  • 看到main函數(shù)中的函數(shù)調(diào)用表達(dá)式answer = fun() - fun() * fun();其實(shí)也是存在一個(gè)歧義的,因?yàn)槟阃耆恢谰幾g器先調(diào)用的是哪個(gè)fun()
//代碼4
int fun()
{
     static int count = 1;
     return ++count;
}
int main()
{
     int answer;
     answer = fun() - fun() * fun();
     printf( "%d\n", answer);//輸出多少?
     return 0;
}
  • 可以看到,若是前面的fun()先執(zhí)行的話,最后的結(jié)果就是-10,若是后面的fun()先執(zhí)行的話,最后的結(jié)果就是-2

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

  • 正常來(lái)說(shuō)大家應(yīng)該都認(rèn)為是第二個(gè)表達(dá)式符合我們的運(yùn)算規(guī)則,因?yàn)?code>先乘除后加減,可是呢我們最常用的VS出來(lái)的結(jié)果都不是我們想要的

我們可以到不同編譯器上面去觀察一下

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

  • 可以看到,雖然在【VS】和【Linux】在執(zhí)行的結(jié)果是-10,而且在大多數(shù)的編譯器下都是這個(gè),但是呢對(duì)于函數(shù)的調(diào)用先后順序無(wú)法通過(guò)操作符的優(yōu)先級(jí)確定,因此這也是一個(gè)問(wèn)題表達(dá)式

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】


⑤ 問(wèn)題表達(dá)式5【VS下反匯編調(diào)試觀察】

  • 好,我們?cè)賮?lái)看最后一個(gè),有關(guān)+++結(jié)合的問(wèn)題表達(dá)式,這個(gè)我在之前的文章中也有提到過(guò),運(yùn)算出來(lái)的結(jié)果其實(shí)是存在歧義的
//代碼5
#include <stdio.h>
int main()
{
	int i = 1;
	int ret = (++i) + (++i) + (++i);
	printf("%d\n", ret);
	printf("%d\n", i);
	return 0;
}

一樣,我們可以到不同的編譯器下去做一個(gè)測(cè)試

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

  • 可以看到,這里就出現(xiàn)了兩個(gè)不同的結(jié)果,在VS里運(yùn)行出來(lái)是【12】,但是在Xshell里面運(yùn)行出來(lái)卻是【10】

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

下面我在VS下通過(guò)調(diào)用反匯編的指令帶大家來(lái)看一下在底層編譯器到底是如何執(zhí)行的,如果不懂可先看看我的這篇文章——> 反匯編深挖【函數(shù)棧幀】的創(chuàng)建和銷毀

  • 將調(diào)試指針移動(dòng)到main函數(shù)的棧幀中代碼所要執(zhí)行的位置,便可以觀察到一些所對(duì)應(yīng)的匯編代碼

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】
第一條指令

00631865 C7 45 F8 01 00 00 00    mov     dword ptr [ebp-8],1
  • 首先我們來(lái)看int i = 1,匯編指令為【mov】,意思是將1這個(gè)值放到main函數(shù)棧幀中ebp - 8這個(gè)位置,也就相當(dāng)于是在這塊位置存放了變量i的地址,然后令它的值為1,那此時(shí)其實(shí)可以想到ebp - 8&i的地址是一致的,我們可以通過(guò)【監(jiān)視窗口】來(lái)觀察一下

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】


第二條指令

0063186C 8B 45 F8        mov      eax,dword ptr [ebp-8]
  • 接下去我們來(lái)看第二條指令,現(xiàn)在已經(jīng)進(jìn)入(++i) + (++i) + (++i)這個(gè)表達(dá)式。可以看到匯編指令為【mov】,通過(guò)后面的命令可以看出是將ebp - 8這塊地址的值放到寄存器eax中去,那么執(zhí)行完后eax = 1

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】


第三條指令

0063186F 83 C0 01       add       eax,1
  • 接下去第三條匯編指令為【add】。很清楚,就是給eax寄存器中的值加1

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】


第四條指令

00631872 89 45 F8        mov       dword ptr [ebp-8],eax
  • 第四條匯編指令為【mov】,意思是將eax所存放的值再放回ebp - 8這塊空間上去。通過(guò)上面一條指令我們知道此時(shí)eax里面存的值為2,并且ebp - 8這塊地址和變量i的地址是一樣的,所以二、三、四條指令也就等價(jià)于++i,只不過(guò)是利用寄存器eax做一個(gè)轉(zhuǎn)移

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】


第五條指令

00631875 8B 4D F8        mov        ecx,dword ptr [ebp-8]
  • 第五條指令是【mov】,作用其實(shí)和第二條是一個(gè)意思,把ebp - 8這塊地址的值放到寄存器ecx中去,那么執(zhí)行完后ecx = 2

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】


第七條指令

00631878 83 C1 01        add         ecx,1
  • 接下去第三條匯編指令為【add】。和第三條是一樣的意思,就是給ecx寄存器中的值加1

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】


第八條指令

0063187B 89 4D F8        mov        dword ptr [ebp-8],ecx
  • 第把條匯編指令為【mov】,和第四條是一樣的意思,將寄存器ecx中存放的值再放回ebp - 8這塊地址中去,也就相當(dāng)于 ++i

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】


第九、十、十一條指令

0063187E 8B 55 F8        mov         edx,dword ptr [ebp-8]  
00631881 83 C2 01        add         edx,1  
00631884 89 55 F8        mov         dword ptr [ebp-8],edx
  • 接下去的第九、十、十一條指令和上面是一樣的,便不再贅述,給出最終結(jié)果

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】


第十二、十三、十四、十五條指令

00631887 8B 45 F8        mov         eax,dword ptr [ebp-8]  
0063188A 03 45 F8        add         eax,dword ptr [ebp-8]  
0063188D 03 45 F8        add         eax,dword ptr [ebp-8]  
00631890 89 45 EC        mov         dword ptr [ebp-14h],eax 

上面這五條指令一起說(shuō),因?yàn)楹蜕厦嫒龡l一樣是行云流水式的

  • 首先將ebp -8里面的值存放到寄存器【eax】里面去

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

  • 然后給【eax】的值加上一個(gè)ebp - 8里面存放的值,那也就是加上一個(gè)i的值,等價(jià)于(++i) + (++i)

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

  • 然后再給【eax】的值加上一個(gè)ebp - 8里面存放的值,等價(jià)于(++i) + (++i) + (++i)

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

  • 最后將上面計(jì)算出來(lái)eax里面的值存放到ebp - 14這塊地址中去,通過(guò)調(diào)試可以看到這塊地址和&ret是一致的,也就是說(shuō)它們是同一塊空間,那也就是將最后的值存放到ret里面去,那么最后打印出來(lái)的ret也就是12

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

通過(guò)反匯編進(jìn)行觀察調(diào)試,這回應(yīng)該清楚了為什么最后的結(jié)果為12了吧

  • 下面是在Linux環(huán)境下通過(guò)objdump進(jìn)行反匯編觀察
objdump -S a.out
  • 在Linux下的反匯編調(diào)試這一塊比較復(fù)雜,就不展開(kāi)細(xì)講,這里你只需要知道對(duì)于操作符而言只有優(yōu)先級(jí)和結(jié)合性,沒(méi)法確定唯一計(jì)算路徑,所以這是一個(gè)問(wèn)題表達(dá)式

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】

十二、總結(jié)與提煉【最后的舞臺(tái)】

好,來(lái)總結(jié)一下本文所學(xué)習(xí)的內(nèi)容?

  • 本文我總共講到了46種操作符,可以說(shuō)是很全了,請(qǐng)讀者觀賞??
  • 算術(shù)操作符:【+ 】、【- 】、【* 】、【/ 】、【% 取余

  • 位操作符:【& 按位與】、【| 按位或】、【^ 按位異或】、【~ 按位取反】、【<< 按位左移】、【>> 按位右移

  • 賦值操作符:【= 賦值】、【+= 復(fù)合加】、【-= 復(fù)合減】、【*= 復(fù)合乘】、【/= 復(fù)合除】、【%= 復(fù)合取余】、【<<= 復(fù)合左移】、【>>= 復(fù)合右移】、【&= 復(fù)合按位與】、【|= 復(fù)合按位或】、【^= 復(fù)合按位異或】、【~= 復(fù)合按位取反

  • 單目操作符:【! 邏輯反】、【- 負(fù)值】、【+ 正值】、【& 取地址】、【sizeof 操作數(shù)的類型長(zhǎng)度】、【- - 前置、后置--】、【++ 前置、后置++】、【* 間接訪問(wèn)】、【() 強(qiáng)制類型轉(zhuǎn)換

  • 關(guān)系操作符:【> 大于】、【>= 大于等于】、【< 小于】、【<= 小于等于】、【!= 不等于】、【== 等于

  • 邏輯操作符:【&& 邏輯與】、【| | 邏輯或

  • 條件操作符:【? 三目運(yùn)算符

  • 逗號(hào)表達(dá)式:【exp1, exp2, exp3, …expN】整個(gè)表達(dá)式的結(jié)果為最后一個(gè)逗號(hào)后面的表達(dá)式

  • 下標(biāo)引用操作符:【[ ]】

  • 函數(shù)調(diào)用操作符:【( )】

  • 結(jié)構(gòu)成員調(diào)用操作符:【.】、【->

  • 最后的話是講到了有關(guān)表達(dá)式的求值相關(guān)的概念。為讀者介紹了隱式類型轉(zhuǎn)換中的【整型提升】,知道了原來(lái)短整型和字符型的數(shù)據(jù)在內(nèi)存中是這樣變化的;然后說(shuō)到【算術(shù)轉(zhuǎn)換】,清楚了再兩個(gè)不同等級(jí)的數(shù)據(jù)類型一起操作的時(shí)候等級(jí)低的會(huì)轉(zhuǎn)化為等級(jí)高的;最后說(shuō)到了各種各樣的【問(wèn)題表達(dá)式】,也帶大家通過(guò)反匯編觀察了編譯器的執(zhí)行邏輯

以上就是本文要介紹的所有內(nèi)容,感謝您的觀看。記得給個(gè)三連哦??????

C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-403911.html

到了這里,關(guān)于C生萬(wàn)物 | 操作符匯總大全【庖丁解牛,精細(xì)講解】的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 【C語(yǔ)言初階】帶你輕松玩轉(zhuǎn)所有常用操作符(1) ——算數(shù)操作符,移位操作符,位操作符

    【C語(yǔ)言初階】帶你輕松玩轉(zhuǎn)所有常用操作符(1) ——算數(shù)操作符,移位操作符,位操作符

    君兮_的個(gè)人主頁(yè) 勤時(shí)當(dāng)勉勵(lì) 歲月不待人 C/C++ 游戲開(kāi)發(fā) Hello,這里是君兮_,最近要準(zhǔn)備期末復(fù)習(xí)了,可能更新的就不會(huì)那么頻繁了,下個(gè)星期恢復(fù)正常更新。 今天給大家?guī)?lái)的是操作符詳解,由于這部分的內(nèi)容比較多,可能會(huì)分成幾部分講,今天帶來(lái)的是第一部分的內(nèi)容,廢

    2024年02月11日
    瀏覽(32)
  • 【PostgreSQL】函數(shù)與操作符-比較函數(shù)和操作符

    PostgreSQL中的比較函數(shù)和操作符用于比較兩個(gè)表達(dá)式的值。它們的作用是確定表達(dá)式的值是否滿足某種條件,例如等于、大于、小于等。 比較函數(shù)是一個(gè)接受兩個(gè)參數(shù)的函數(shù),返回一個(gè)布爾值,表示兩個(gè)參數(shù)是否滿足某種條件。例如,equal()函數(shù)用于判斷兩個(gè)參數(shù)是否相等,

    2024年01月17日
    瀏覽(57)
  • 初始C語(yǔ)言——詳細(xì)講解操作符以及操作符的易錯(cuò)點(diǎn)

    初始C語(yǔ)言——詳細(xì)講解操作符以及操作符的易錯(cuò)點(diǎn)

    ?第一章?“C“滸傳——初識(shí)C語(yǔ)言(更適合初學(xué)者體質(zhì)哦!) ?第二章?詳細(xì)認(rèn)識(shí)分支語(yǔ)句和循環(huán)語(yǔ)句以及他們的易錯(cuò)點(diǎn)? ?第三章?初階C語(yǔ)言——特別詳細(xì)地介紹函數(shù) ?第四章?初始C語(yǔ)言——詳細(xì)地講解數(shù)組的內(nèi)容以及易錯(cuò)點(diǎn) ?第五章? 初始C語(yǔ)言——詳細(xì)講解操作符以及操

    2024年02月13日
    瀏覽(36)
  • 庖丁解牛函數(shù)知識(shí)---C語(yǔ)言《1》

    庖丁解牛函數(shù)知識(shí)---C語(yǔ)言《1》

    目錄 前言: 1.程序中的函數(shù) 2.庫(kù)函數(shù)的學(xué)習(xí)和使用 3.自定義函數(shù) 4.傳值調(diào)用與傳址調(diào)用 5.形參與實(shí)參 6.練習(xí)---二分查找函數(shù) ?博主CSDN:啊蘇要學(xué)習(xí) ? ?專欄分類:C語(yǔ)言? ? C語(yǔ)言的學(xué)習(xí),是為我們今后學(xué)習(xí)其它語(yǔ)言打好基礎(chǔ),C生萬(wàn)物! ? 開(kāi)始我們的C語(yǔ)言之旅吧!? ? 在計(jì)

    2024年02月02日
    瀏覽(16)
  • 庖丁解牛函數(shù)知識(shí)---C語(yǔ)言《2》

    庖丁解牛函數(shù)知識(shí)---C語(yǔ)言《2》

    目錄 前言: 1.嵌套調(diào)用函數(shù) 2.鏈?zhǔn)皆L問(wèn) 3.函數(shù)的聲明與定義 4.*遞歸 5.遞歸與非遞歸 ?博主CSDN:啊蘇要學(xué)習(xí) ? ?專欄分類:C語(yǔ)言? ? C語(yǔ)言的學(xué)習(xí),是為我們今后學(xué)習(xí)其它語(yǔ)言打好基礎(chǔ),C生萬(wàn)物! ? 開(kāi)始我們的C語(yǔ)言之旅吧!? ? 在第一篇的基礎(chǔ)上,我們接著學(xué)習(xí)函數(shù)相關(guān)的

    2024年02月02日
    瀏覽(24)
  • 【c語(yǔ)言操作符系列1】^(異或操作符)講解和多種例題詳解

    【c語(yǔ)言操作符系列1】^(異或操作符)講解和多種例題詳解

    目錄 一、^ 是什么(^稱為異或) 二、^的規(guī)律(特點(diǎn)) 三、可利用^秒殺的常見(jiàn)例題(重點(diǎn)) 1、消失的數(shù)字 ?2、不一樣的人生密碼 3、交換兩個(gè)數(shù)(不能創(chuàng)建中間變量) 4、找出只出現(xiàn)一個(gè)的兩個(gè)數(shù)字 是一種操作符, 針對(duì)二進(jìn)制異或而言的 ,兩個(gè)數(shù)對(duì)應(yīng)的二進(jìn)制位相同,異或

    2024年02月16日
    瀏覽(27)
  • Js中.?和??語(yǔ)法(可選鏈操作符和雙問(wèn)號(hào)操作符)

    Js中.?和??語(yǔ)法(可選鏈操作符和雙問(wèn)號(hào)操作符)

    Tips:為啥起這么一個(gè)標(biāo)題呢,因?yàn)槲易约寒?dāng)時(shí)看代碼,看到這個(gè)語(yǔ)法的時(shí)候就感覺(jué)有些遺忘,但是又不知道他叫做什么名字,所以只能直接搜索.?和??這樣搜索,哈哈哈相信不少人可能跟我一樣,不知道他叫做什么名字嘿嘿。 可選鏈 操作符( ?. )允許讀取位于連接對(duì)象鏈深

    2024年01月21日
    瀏覽(27)
  • 【數(shù)據(jù)結(jié)構(gòu)】 隊(duì)列詳解!庖丁解牛般細(xì)致講解!

    【數(shù)據(jù)結(jié)構(gòu)】 隊(duì)列詳解!庖丁解牛般細(xì)致講解!

    ?? 嶼小夏 : 個(gè)人主頁(yè) ??個(gè)人專欄 : 數(shù)據(jù)結(jié)構(gòu)解析 ?? 莫道桑榆晚,為霞尚滿天! 什么是隊(duì)列?隊(duì)列有什么樣的特性?它的應(yīng)用場(chǎng)景有哪些? 本文會(huì)對(duì)隊(duì)列這種數(shù)據(jù)結(jié)構(gòu)進(jìn)行進(jìn)行庖丁解牛般的講解,讓你徹底學(xué)會(huì)數(shù)據(jù)結(jié)構(gòu)! 隊(duì)列是一種常見(jiàn)的數(shù)據(jù)結(jié)構(gòu),它按照先進(jìn)先出

    2024年02月06日
    瀏覽(20)
  • 【C語(yǔ)言】中的位操作符和移位操作符,原碼反碼補(bǔ)碼以及進(jìn)制之間的轉(zhuǎn)換

    【C語(yǔ)言】中的位操作符和移位操作符,原碼反碼補(bǔ)碼以及進(jìn)制之間的轉(zhuǎn)換

    歡迎大家來(lái)到c語(yǔ)言知識(shí)小課堂,今天的知識(shí)點(diǎn)是操作符和進(jìn)制 同樣都是數(shù)字1111,不同進(jìn)制下數(shù)字的大小不同,第二行代表的是其各位數(shù)字十進(jìn)制下的大小,將各位數(shù)字的十進(jìn)制大小相加即1111在這個(gè)進(jìn)制下轉(zhuǎn)化為十進(jìn)制的大小,從圖中我們可以看出來(lái) 進(jìn)制的定義:從右往左

    2024年02月22日
    瀏覽(24)
  • 前端JS實(shí)用操作符,一些騷操作?

    前端JS實(shí)用操作符,一些騷操作?

    ???????? 目錄 0、!!? 雙重邏輯非操作符???? 1、?? 操作符 空值合并/空判斷??? 2、?. 可選鏈運(yùn)算符?? 3、??= 操作符 邏輯空值賦值運(yùn)算符??? 4、三元運(yùn)算符??? 5、~~ 操作符 雙位運(yùn)算符??? 6、與 ||或 短路運(yùn)算符??? 7、| 0 取整??? 8、 1 判斷奇偶數(shù)??? 9、_ 數(shù)值分割

    2024年02月14日
    瀏覽(26)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包