國外商業(yè)網(wǎng)站建設(shè)無錫百度seo優(yōu)化
致前行的人:? ??
????????人生像攀登一座山,而找尋出路,卻是一種學(xué)習(xí)的過程,我們應(yīng)當(dāng)在這過程中,學(xué)習(xí)穩(wěn)定冷靜,學(xué)習(xí)如何從慌亂中找到生機(jī)。
目錄
1.注釋符號:
2.續(xù)接符和轉(zhuǎn)義符:
3.回車與換行:
4.單引號和雙引號:
5.計(jì)算機(jī)為何存在字符:
6.邏輯運(yùn)算符:
7.位運(yùn)算符:
8.如何理解整型提升
9.左移和右移?
10++、--操作
10.1深刻理解 a++
10.2++,--使用時(shí)會存在的問題
11.符號
1.注釋符號:
注:注釋在預(yù)處理的時(shí)候本質(zhì)上是被替換成空格?
C分格的注釋不支持嵌套:
?/*總是離它最近的*/匹配
注釋與指針:
?當(dāng)/*在一起的時(shí)候編譯器會默認(rèn)為注釋符號,為了避免應(yīng)該加上():
2.續(xù)接符和轉(zhuǎn)義符:
1.續(xù)行功能:
\:這里\充當(dāng)續(xù)行的功能
注意:\的后面不能出現(xiàn)任何任何字符包括空格
?2.轉(zhuǎn)義功能:
1.字面轉(zhuǎn)特殊:
2.特殊轉(zhuǎn)字面:
?
3.回車與換行:
回車:是將光標(biāo)從當(dāng)前的位置移動(dòng)到開始位置? ?\n
換行:是移動(dòng)到下一行? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?\r
驗(yàn)證:倒計(jì)時(shí)
4.單引號和雙引號:
單引號是字符,雙引號是字符串:
5.計(jì)算機(jī)為何存在字符:
為何會存在ASCCII表?
1.數(shù)據(jù)在內(nèi)存中存儲是以二進(jìn)制的形式存儲的,而為了讓用戶在顯示器上清楚易懂的讀取,則創(chuàng)造了不同的二進(jìn)制對應(yīng)不同的字符。2.每一種字符又是英語是因?yàn)橛?jì)算機(jī)最早是美國人發(fā)明的,而他們的語言又是英語,為了簡單則用不同的英文字母來對應(yīng)二進(jìn)制數(shù)據(jù)
6.邏輯運(yùn)算符:
&&:并且 兩個(gè)條件為真則為真
||:或? ? ? ?有一個(gè)條件為真則為真
?短路:
&&:當(dāng)前面的條件為假時(shí)后面的表達(dá)式不進(jìn)行
||:? ?當(dāng)前面的條件為真時(shí)后面的表達(dá)式不執(zhí)行
7.位運(yùn)算符:
&:按位與 相同則為1,相異則為0
|:按位或? 有一個(gè)為1則為1
^:按位異或 相異則為1,相同則為0
~:按位取反?
^的理解:
^:逐比特位,相同則為0,相異為1
任何數(shù)和0異或,都是它本身?
支持結(jié)合律和交換律?
?交換兩個(gè)整數(shù):
方法1:創(chuàng)建臨時(shí)變量
void swap(int* p1, int* p2)
{int tmp = *p1;*p1 = *p2;*p2 = tmp;
}
int main()
{printf("before:a = %d,b = %d\n", a, b);int a = 10;int b = 20;swap(&a, &b);printf("after:a = %d,b = %d\n", a, b);return 0;
}
方法2: 不創(chuàng)建臨時(shí)變量
int main()
{int a = 10;int b = 20;printf("before:a = %d,b = %d\n", a, b);a = a + b;b = a - b;a = a - b;printf("after:a = %d,b = %d\n", a, b);return 0;
}
存在的問題:當(dāng)a和b是兩個(gè)非常大的數(shù)時(shí),由于相加就可能會存在整型溢出的問題
方法3:用異或解決整型溢出的問題
int main()
{int a = 10;int b = 20;printf("before:a = %d,b = %d\n", a, b);a = a ^ b;b = a ^ b;a = a ^ b;printf("after:a = %d,b = %d\n", a, b);return 0;
}
?圖例解釋:
將指定bit位置為1 :
將指定bit位置為0:
#define SETBIT(x,n) (x |= (1 << (n - 1))) //將指定bit位置為1
#define CLRBIT(x,n) (x &= (~(1 << (n-1)))) //將指定bit位置為0
void show_bits(int x)
{int num = sizeof(x) * 8 - 1;while (num >= 0){if (x & (1 << num))printf("1 ");elseprintf("0 ");num--;}
}
int main()
{int x = 10;SETBIT(x, 5);CLRBIT(x, 5);show_bits(x);return 0;
}
8.如何理解整型提升
無論任何位運(yùn)算符,目標(biāo)都是要計(jì)算機(jī)進(jìn)行計(jì)算的,而計(jì)算機(jī)中只有CPU具有運(yùn)算能力(先這樣簡單理解),但計(jì)算的數(shù)據(jù),都在內(nèi)存中。故,計(jì)算之前(無論任何運(yùn)算),都必須將數(shù)據(jù)從內(nèi)存拿到CPU中,拿到CPU哪里呢?毫無疑問,在CPU 寄存器中。
而寄存器本身,隨著計(jì)算機(jī)位數(shù)的不同,寄存器的位數(shù)也不同。一般,在32位下,寄存器的位數(shù)是32位??墒?#xff0c;你的char類型數(shù)據(jù),只有8比特位。讀到寄存器中,只能填補(bǔ)低8位,那么高24位呢?就需要進(jìn)行“整形提升”。
#include<stdio.h>
int main()
{char c = 0;printf("sizeof(c): %d\n", sizeof(c)); printf("sizeof(c): %d\n", sizeof(~c)); printf("sizeof(c): %d\n", sizeof(c << 1)); printf("sizeof(c): %d\n", sizeof(c >> 1));return 0;
}
9.左移和右移?
<<(左移): 最高位丟棄,最低位補(bǔ)零
>>(右移):
1. 無符號數(shù):最低位丟棄,最高位補(bǔ)零[邏輯右移]
2. 有符號數(shù):最低位丟棄,最高位補(bǔ)符號位[算術(shù)右移]
int main()
{//左移unsigned int a = 1;printf("%u\n", a << 1);printf("%u\n", a << 2);printf("%u\n", a << 3);return 0;
}
int main()
{// 邏輯右移unsigned int b = 100;printf("%u\n", b >> 1);printf("%u\n", b >> 2);printf("%u\n", b >> 3);return 0;
}
?
int main()
{// 算術(shù)右移,最高位補(bǔ)符號位1,雖然移出了最低位1,但是補(bǔ)得還是1int c = -1;printf("%d\n", c >> 1);printf("%d\n", c >> 2);printf("%d\n", c >> 3);return 0;
}
?
int main()
{unsigned int d = -1;printf("%d\n", d >> 1);printf("%d\n", d >> 2);printf("%d\n", d >> 3);return 0;
}
?
結(jié)論:
左移,無腦補(bǔ)0
右移,先判定是算術(shù)右移還是邏輯右移,判定依據(jù):看自身類型,和變量的內(nèi)容無關(guān)。
10++、--操作
int main()
{int a = 10;int b = ++a; //前置++, 先自增在使用printf("%d, %d\n", a, b); //11,11int c = 10;int d = c++; //后置++,先使用在自增printf("%d, %d\n", c, d); //11,10//--同上return 0;
}
10.1深刻理解 a++
int main()
{int a = 10;int b = a++;int c = 20;c++;return 0;
}
結(jié)論:a++完整的含義是先使用,在自增。如果沒有變量接收,那么直接自增
10.2++,--使用時(shí)會存在的問題
int main()
{int i = 1;int j = (++i) + (++i) + (++i);printf("%d\n", j);return 0;
}
上面代碼,分別在不同的編譯器下試試,可能會得到不同結(jié)果
在Linux下測試結(jié)果為10,在VS上測試結(jié)果為12
本質(zhì):是因?yàn)樯厦姹磉_(dá)式的"計(jì)算路徑不唯一"(為什么?編譯器識別表達(dá)式,是同時(shí)加載至寄存器,還是分批加載,完全不確定)導(dǎo)致的,類似這種復(fù)雜表達(dá)式,不推薦使用。
表達(dá)式匹配:貪心算法
編譯器在處理復(fù)雜表達(dá)式的時(shí)候,會盡可能將多個(gè)運(yùn)算符組成表達(dá)式進(jìn)行運(yùn)算
int main()
{int a = 10;int b = 20;//printf("%d\n", a++++ + b);//自動(dòng)匹配失敗 errprintf("%d\n", a++ + ++b); //自行分離匹配,非常不推薦,不過能看出空格的好處 31return 0;
}
11.符號
深度理解取余/取模運(yùn)算
step 1:向0取整
int main()
{int i = -2.9;int j = 2.9;printf("%d\n", i); //結(jié)果是:-2printf("%d\n", j); //結(jié)果是:2return 0;
}
?如圖所示:
在庫中有一個(gè)trunc取整函數(shù),同作用:
#include<math.h>
int main()
{printf("%d\n",(int)trunc(-2.9));printf("%d\n", (int)trunc(2.9));return 0;
}
step 2:向-∞取整
如圖所示:
int main()
{//本質(zhì)是向-∞取整,注意輸出格式要不然看不到結(jié)果printf("%.1f\n", floor(-2.9));printf("%.1f\n", floor(-2.1));printf("%.1f\n", floor(2.9));printf("%.1f\n", floor(2.1));return 0;
}
?step3:向+∞取整
如圖所示:
int main()
{//本質(zhì)是向+∞取整,注意輸出格式要不然看不到結(jié)果printf("%.1f\n", ceil(-2.9));printf("%.1f\n", ceil(-2.1));printf("%.1f\n", ceil(2.9));printf("%.1f\n", ceil(2.1));return 0;
}
?
step4:四舍五入?
int main()
{//本質(zhì)是四舍五入printf("%.1f\n", round(2.1));printf("%.1f\n", round(2.9));printf("%.1f\n", round(-2.1));printf("%.1f\n", round(-2.9));return 0;
}
?取模概念:
如果a和d是兩個(gè)自然數(shù),d非零,可以證明存在兩個(gè)唯一的整數(shù) q 和 r,滿足 a = q*d + r 且0 ≤ r < d。其中,q被稱為商,r 被稱為余數(shù)。
int main()
{int a = 10;int d = 3;printf("%d\n", a % d); //結(jié)果是1//因?yàn)?#xff1a;a=10,d=3,q=3,r=1 ??0<= r <d(3)//所以:a = q*d+r -> 10=3*3+1return 0;
}
如果是下面的代碼呢?
int main()
{int a = -10;int d = 3;printf("%d\n", a % d); //結(jié)果是-1return 0;
}
python環(huán)境:
?結(jié)論:很顯然,上面關(guān)于取模的定義,并不能滿足語言上的取模運(yùn)算
因?yàn)樵贑中,現(xiàn)在-10%3出現(xiàn)了負(fù)數(shù),根據(jù)定義:滿足 a = q*d + r 且0 ≤ r < d,C語言中的余數(shù),是不滿足定義的,因?yàn)?#xff0c;r<0了。
故,大家對取模有了一個(gè)修訂版的定義:
如果a和d是兩個(gè)自然數(shù),d非零,可以證明存在兩個(gè)唯一的整數(shù) q 和 r,滿足 a = q*d + r , q 為整數(shù),且0 ≤ |r|< |d|。其中,q 被稱為商,r 被稱為余數(shù)。
有了這個(gè)新的定義,那么C中或者Python中的“取模”,就都能解釋了。
解釋C: -10 = (-3) * 3 + (-1)
解釋Python:-10 = (?)* 3 + 2,其中,可以推到出來,'?'必須是-4(后面驗(yàn)證).即-10 = (-4)* 3 + 2,才能滿足定義。
所以,在不同語言,同一個(gè)計(jì)算表達(dá)式,負(fù)數(shù)“取?!苯Y(jié)果是不同的。我們可以稱之為分別叫做正余數(shù) 和 負(fù)余數(shù)
由上面的例子可以看出,具體余數(shù)r的大小,本質(zhì)是取決于商q的。而商,又取決誰呢?取決于除法計(jì)算的時(shí)候,取整規(guī)則。
本質(zhì) 1 取整:
取余:盡可能讓商,進(jìn)行向0取整。
取模:盡可能讓商,向-∞方向取整。
故:
C中%,本質(zhì)其實(shí)是取余。
Python中%,本質(zhì)其實(shí)是取模。
理解鏈:
對任何一個(gè)大于0的數(shù),對其進(jìn)行0向取整和-∞取整,取整方向是一致的。故取模等價(jià)于取余
對任何一個(gè)小于0的數(shù),對其進(jìn)行0向取整和-∞取整,取整方向是相反的。故取模不等價(jià)于取余
同符號數(shù)據(jù)相除,得到的商,一定是正數(shù)(正數(shù)vs正整數(shù)),即大于0!故,在對其商進(jìn)行取整的時(shí)候,取模等價(jià)于取余。
計(jì)算數(shù)據(jù)同符號:
C:
int main()
{printf("%d\n", 10 / 3);printf("%d\n\n", 10 % 3);printf("%d\n", -10 / -3);printf("%d\n\n", -10 % -3);return 0;
}
?python:
print(10 // 3)
print(10 % 3)
print(-10 // -3)
print(-10 % -3)
注:python中 / 默認(rèn)是浮點(diǎn)數(shù)除法,//才是整數(shù)除法,并進(jìn)行-∞取整?
通過對比試驗(yàn),更加驗(yàn)證了,參與取余的兩個(gè)數(shù)據(jù),如果同符號,取模等價(jià)于取余
如果參與運(yùn)算的數(shù)據(jù),不同符號呢?
C:
int main()
{printf("%d\n", -10 / 3); //結(jié)果:-3printf("%d\n\n", -10 % 3); //結(jié)果:-1 -> -10=(-3)*3+(-1)printf("%d\n", 10 / -3);//結(jié)果:-3printf("%d\n\n", 10 % -3);//結(jié)果:1 -> 10=(-3)*(-3)+1return 0;
}
python:
print(-10 // 3)
print(-10 % 3)
print(10 // -3)
print(10 % -3)
重新看看定義:
如果a和d是兩個(gè)自然數(shù),d非零,可以證明存在兩個(gè)唯一的整數(shù) q 和 r,滿足 a = q*d + r , q 為整數(shù),且0 ≤ |r|< |d|。其中,q 被稱為商,r 被稱為余數(shù)。
a = q*d + r 變換成 r = a - q*d 變換成 r = a + (-q*d) ,對于:x = y + z,這樣的表達(dá)式,x的符號 與 |y|、|z|中大的數(shù)據(jù)一致
而r = a + (-q*d)中,|a| 和 |-q*d|的絕對值誰大,取決于商q的取整方式。
c是向0取整的,也就是q本身的絕對值是減小的。
如:
-10/3=-3.333.33 向0取整 -3. ?a=-10 |10|, -q*d=-(-3)*3=9 |9|
10/-3=-3.333.33 向0取整 -3. ?a=10 |10|, -q*d=-(-3)*(-3)=-9 |9|
絕對值都變小了
python是向-∞取整的,也就是q本身的絕對值是增大的。
-10/3=-3.333.33 ?'//'向-∞取整 -4. ?a=-10 |10|, -q*d=-(-4)*3=12 |12|
10/-3=--3.333.33 '//'向-∞取整 -4. ?a=10 |10|, -q*d=-(-4)*(-3)=-12 |12|
絕對值都變大了
結(jié)論:如果參與取余的兩個(gè)數(shù)據(jù)符號不同,在C語言中(或者其他采用向0取整的語言如:C++,Java),余數(shù)符號,與被除數(shù)相同。
總結(jié):
浮點(diǎn)數(shù)(或者整數(shù)相除),是有很多的取整方式的。
如果a和d是兩個(gè)自然數(shù),d非零,可以證明存在兩個(gè)唯一的整數(shù) q 和 r,滿足 a = q*d + r , q 為整數(shù),且0 ≤ |r|< |d|。其中,q 被稱為商,r 被稱為余數(shù)。
在不同語言,同一個(gè)計(jì)算表達(dá)式,“取模”結(jié)果是不同的。我們可以稱之為分別叫做正余數(shù)和負(fù)余數(shù)
具體余數(shù)r的大小,本質(zhì)是取決于商q的。而商,又取決于除法計(jì)算的時(shí)候,取整規(guī)則。
取余vs取模: 取余盡可能讓商,進(jìn)行向0取整。取模盡可能讓商,向-∞方向取整。
參與取余的兩個(gè)數(shù)據(jù),如果同符號,取模等價(jià)于取余
如果參與取余的兩個(gè)數(shù)據(jù)符號不同,在C語言中(或者其他采用向0取整的語言如:C++,Java),余數(shù)符號,與被除數(shù)相同。(因?yàn)椴捎玫南?取整)