網(wǎng)站開(kāi)發(fā)企劃書(shū)網(wǎng)站收錄檢測(cè)
簡(jiǎn)介
學(xué)習(xí)計(jì)算機(jī),離不開(kāi)C語(yǔ)言的學(xué)習(xí),而C語(yǔ)言學(xué)習(xí)過(guò)程中的視頻課教程,目前來(lái)說(shuō),如果郝斌老師的C語(yǔ)言排第二,沒(méi)有人敢排第一
郝斌老師的C語(yǔ)言教程,通俗易懂,引人發(fā)思,特別適合新手入門(mén)以及提高,強(qiáng)烈推薦學(xué)習(xí)
在學(xué)習(xí)過(guò)程中,記錄了一些筆記,現(xiàn)整理出來(lái)做博客,供大家參考~
學(xué)習(xí)視頻地址:《C語(yǔ)言學(xué)習(xí)》
學(xué)習(xí)方法論
在學(xué)習(xí)某個(gè)新知識(shí)點(diǎn)的時(shí)候,可以用以下方法論來(lái)進(jìn)行學(xué)習(xí):
WWHA
What:什么是A?
Why:為什么需要A?
How:怎么使用A?
Attention:需要注意哪些問(wèn)題?
C語(yǔ)言學(xué)習(xí)推薦的參考資料:
譚浩強(qiáng)《C語(yǔ)言程序設(shè)計(jì)》
ps:這本書(shū)是又愛(ài)又恨
《C和指針》
《C專(zhuān)家編程》
《C陷阱與缺陷》
林銳:《高質(zhì)量C/C++編程》
變量
什么是變量?
變量的本質(zhì)就是內(nèi)存中一段存儲(chǔ)空間
數(shù)據(jù)存儲(chǔ)是以“字節(jié)”(Byte)為單位,數(shù)據(jù)傳輸大多是以“位”(bit,又名“比特”)為單位
一個(gè)位就代表一個(gè)0或1(即二進(jìn)制),每8個(gè)位(bit,簡(jiǎn)寫(xiě)為b)組成一個(gè)字節(jié)(Byte,簡(jiǎn)寫(xiě)為B),是最小一級(jí)的信息單位。
1字節(jié)(Byte) = 8位(bit)
1bit就是二進(jìn)制的0和1
計(jì)算機(jī)能夠處理的最小單元是 字節(jié) 而不是位
位,是由軟件通過(guò)位運(yùn)算符操作的
1個(gè)英文字母(不分大小寫(xiě))占一個(gè)字節(jié)的空間
D十進(jìn)制 B二進(jìn)制 O八進(jìn)制 H十六進(jìn)制
基本數(shù)據(jù)類(lèi)型所占字節(jié)大小:
char 1個(gè)字節(jié)
int float 4個(gè)字節(jié)
double 8個(gè)字節(jié)
可以用sizeof()驗(yàn)證
其他類(lèi)型所占字節(jié)大小:
ASCII碼關(guān)鍵值:
‘0’ = 48 ‘1’ = 49…
A = 65 B = 66…
a = 97 b = 98…
關(guān)于數(shù)值不夠存儲(chǔ),溢出情況:
char 占1個(gè)字節(jié),8位,范圍是 -27 ~ 27 - 1 = -128 ~ 127
char a = 127; 使用%d打印出來(lái)是127
char a = 128; 使用%d打印出來(lái)是-128
char a = 129; 使用%d打印出來(lái)是-127
char a = 130; 使用%d打印出來(lái)是-126
scanf輸入
scanf的作用:將從鍵盤(pán)輸入的字符轉(zhuǎn)化為輸入控制符所規(guī)定格式的數(shù)據(jù),然后存入以輸入?yún)?shù)的值為地址的變量中。
sacnf("%d", &i);
中,%d的作用?
在輸入過(guò)程中,我們輸入的都是字符1,字符2,字符3,系統(tǒng)接收數(shù)據(jù),都是接收字符。系統(tǒng)如何能夠知道我們輸入的123,是一百二十三,而不是123呢?
這就需要%d的作用,讓系統(tǒng)知道我們輸入的是什么。
余數(shù)與正負(fù)符號(hào)的關(guān)系
13%3 == 1
13%-3 == 1
-13%3 == -1
-13%23 == -13
-13%-23 == -13
即,取余后的符號(hào),只與前面的數(shù)據(jù)符號(hào)有關(guān)系
i+=1與i++的區(qū)別
i+=1;內(nèi)存->寄存器->內(nèi)存
i++;直接在寄存器中處理
逗號(hào)表達(dá)式
格式:
(A, B, C, D)
功能:
從左到右執(zhí)行
最終表達(dá)式的值,是最后一項(xiàng)的值
流程控制
順序 選擇 循環(huán)
技巧:如何看懂一個(gè)程序?
1流程
2每個(gè)語(yǔ)句的功能
3試數(shù)(把程序運(yùn)行一下)
switch
執(zhí)行完一個(gè)case語(yǔ)句后,流程控制就轉(zhuǎn)移到下一個(gè)case字句繼續(xù)執(zhí)行?!癱ase”常量表達(dá)式只是起語(yǔ)句標(biāo)號(hào)的作用,并不是在該處進(jìn)行條件判斷。在執(zhí)行switch語(yǔ)句時(shí),根據(jù)switch()中表達(dá)式的值找到與之匹配的case子句,就從此case子句開(kāi)始執(zhí)行下去,不再進(jìn)行判斷。
白話:case只是程序的入口,當(dāng)找到入口后,就會(huì)順序執(zhí)行下面的所有語(yǔ)句(當(dāng)然,case語(yǔ)句沒(méi)啥意義,不算)
若val = 5,直接是default開(kāi)始
若val=2,是從2開(kāi)始的,而不是順序執(zhí)行從default開(kāi)始的。
白話:就是找入口,不是順序找;會(huì)遍歷里面所有的case,有的話匹配,沒(méi)有的話default。
break continue:
- break如果用于循環(huán),是用來(lái)終止循環(huán)
- break如果用于switch,則是用于終止switch
- break不能直接用于if,除非if屬于循環(huán)內(nèi)部的一個(gè)子句(這句話的意思是,如果在if內(nèi)部見(jiàn)到了break,請(qǐng)注意,它不作用在if上,break作用在循環(huán)中)
- 在多層循環(huán)中,break只能終止距離它最近的那個(gè)循環(huán)
- 在多層switch嵌套中,break只能終止距離它最近的switch
白話:break 是結(jié)束此次循環(huán)
continue用于跳過(guò)本次循環(huán)余下的語(yǔ)句,轉(zhuǎn)去判斷是否需要執(zhí)行下次循環(huán)
白話:continue是跳過(guò)循環(huán)后面的語(yǔ)句,再次循環(huán)
作業(yè)題:
- 判斷一個(gè)數(shù)字是否是素?cái)?shù)?
- 判斷一個(gè)數(shù)字是否是回文數(shù)?
- 編程實(shí)現(xiàn)求一個(gè)十進(jìn)制數(shù)字的二進(jìn)制形式?
- 求一個(gè)數(shù)字的每位是奇數(shù)的數(shù)字取出來(lái)組合形成新數(shù)字?
- 求一個(gè)數(shù)字倒過(guò)來(lái)的數(shù)字?
- 斐波那契數(shù)列
郝斌老師對(duì)算法程序?qū)W習(xí)的一些建議:
- 嘗試自己去編程解決它,大部分人都自己無(wú)法解決。如果過(guò)了15分鐘還想不出來(lái),此時(shí)我建議你就可以看答案了。
- 如果解決不了,就看答案。關(guān)鍵是把答案看懂,這個(gè)要花很大的精力,也是我們學(xué)習(xí)的重點(diǎn)。
- 看懂之后嘗試自己去修改程序,并且知道修改之后程序的不同輸出結(jié)果的含義。
- 照著答案去敲。
- 調(diào)試錯(cuò)誤。
- 不看答案,自己獨(dú)立把答案敲出來(lái)。
- 如果程序?qū)嵲跓o(wú)法徹底理解,就把它背會(huì)
是否是回文數(shù),也可使用這種判斷:
int zuiHouYiWei = 0;int shengYu = value;while (shengYu) {zuiHouYiWei = shengYu%10;shengYu = shengYu/10;sum = sum*10 + zuiHouYiWei;printf("zuiHouYiWei的值是:%d\n", zuiHouYiWei);printf("shengYu的值是:%d\n", shengYu);printf("sum的值是:%d\n", sum);printf("------------\n");}
數(shù)組
一維數(shù)組:
怎么定義一維數(shù)組:
- 為n個(gè)變量連續(xù)分配內(nèi)存空間(數(shù)組的內(nèi)存一定是連續(xù)分配的!)
- 所有的變量,數(shù)據(jù)類(lèi)型必須相同
- 所有變量所占的字節(jié)大小必須相等
有關(guān)一維數(shù)組的操作:
初始化、賦值、排序、求最大值\最小值、倒置、查找、插入、刪除
初始化:
-
完全初始化
int [5] = {1, 2, 3, 4, 5}; -
不完全初始化,未被初始化的元素自動(dòng)為零
int a[5] = {1, 2, 3};//a[3] = a[4] = 0; -
不初始化,所有元素是垃圾值
int [5]; -
清零
int a[5] = {0};
錯(cuò)誤寫(xiě)法:
int a[5];
a[5] = {1, 2, 3, 4, 5};//錯(cuò)誤
原因:只有在定義數(shù)組的同時(shí)才可以整體賦值,其他情況下整體賦值都是錯(cuò)誤的。另:a數(shù)組,并沒(méi)有a[5]元素
只有在定義的時(shí)候,5表示個(gè)數(shù);其他在任意地方出現(xiàn),只是表示下標(biāo),而非個(gè)數(shù)。
兩個(gè)數(shù)組之間賦值
int a[5] = {1, 2, 3, 4, 5};
int b[5];
如果要把數(shù)組a中的值全部復(fù)制給b數(shù)組,
錯(cuò)誤的寫(xiě)法: b = a;
a、b代表的數(shù)組名,數(shù)組名是第一個(gè)元素的地址。
正確的寫(xiě)法
for (i = 0; i < 5; i++)
{b[i] = a[i];
}
二維數(shù)組:
int a[3][4] 總共12個(gè)元素,可以當(dāng)做3X4看待
a[0][0] a[0][1] a[0][2] a[0][3]
a[1][0] a[1][1] a[1][2] a[1][3]
a[2][0] a[2][1] a[2][2] a[2][3]
a[i][j] 表示的是第i+1行,第j+1列的元素
初始化:
int a[3][4] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
int a[3][4] = {{1, 2, 3, 4},{5, 6, 7, 8},{9, 10, 11, 12}
};
操作:
二維數(shù)組的輸出
二維數(shù)組的排序
求每一行的最大值
判斷矩陣是否對(duì)稱(chēng)
多維數(shù)組
是否存在多維數(shù)組:不存在
原因:因?yàn)閮?nèi)存是線性一維的
n維數(shù)組可以當(dāng)做每個(gè)元素是n-1維數(shù)組的數(shù)組
比如:int[3][4],可以看成3個(gè)一維數(shù)組,每個(gè)數(shù)組里面有4個(gè)元素。
函數(shù)
對(duì)庫(kù)函數(shù)的聲明是通過(guò)與 #include<庫(kù)函數(shù)所在的文件的名字.h> 來(lái)實(shí)現(xiàn)的
return 是終止整個(gè)函數(shù)的,即,遇到return,函數(shù)就結(jié)束
變量的作用域和存儲(chǔ)方式:
按作用域分:
- 全局變量
在所有函數(shù)外部定義的變量叫全局變量
全局變量的使用范圍:從定義位置開(kāi)始到整個(gè)程序結(jié)束 - 局部變量
在一個(gè)函數(shù)內(nèi)部定義的變量,或者函數(shù)的形參,都統(tǒng)稱(chēng)為局部變量
局部變量的使用范圍:只能在本函數(shù)內(nèi)部使用
注意的問(wèn)題:
全局變量和局部變量命名沖突:局部變量屏蔽全局變量
按變量的存儲(chǔ)方式:
靜態(tài)變量
自動(dòng)變量
寄存器變量
如何在軟件開(kāi)發(fā)中合理的設(shè)計(jì)函數(shù)來(lái)解決實(shí)際問(wèn)題?
一個(gè)函數(shù)的功能盡量獨(dú)立、單一
多學(xué)習(xí),多模仿牛人的代碼
指針
指針就是地址
地址就是內(nèi)存單元的編號(hào)
每一個(gè)小單元,有8位(8個(gè)0,或8個(gè)1)
也就是說(shuō),內(nèi)存的編號(hào)不是以位算的,是以字節(jié)算的
地址一般用16進(jìn)制表示(32位的操作系統(tǒng)中,地址是32/8=4個(gè)字節(jié)。64位系統(tǒng)中,地址占8個(gè)字節(jié))
指針的定義
地址
內(nèi)存單元的編號(hào)
從零開(kāi)始的非負(fù)整數(shù)
范圍:4G【0-4G-1】
指針
指針的本質(zhì)就是 一個(gè)操作受限的 非負(fù)整數(shù)(只能-,不能+*/)
指針、指針變量
指針就是地址,地址就是指針
指針變量就是存放地址的變量 也可以說(shuō) 指針變量就是存放指針的變量
例如 int *p中p就是指針變量。
需要注意:通常我們敘述時(shí),會(huì)把指針變量簡(jiǎn)稱(chēng)為指針,實(shí)際上它們的含義并不一樣
指針的重要性
可以表示一些復(fù)雜的數(shù)據(jù)結(jié)構(gòu);
快速的傳遞數(shù)據(jù);
使函數(shù)返回一個(gè)以上的值;
直接訪問(wèn)硬件;
能夠方便的處理字符串;
是理解面向?qū)ο笳Z(yǔ)言中引用的基礎(chǔ)
總結(jié):指針是C語(yǔ)言的靈魂
指針的分類(lèi)
1 基本類(lèi)型指針
如何通過(guò)被調(diào)函數(shù)修改主調(diào)函數(shù)普通變量的值?
- 1 實(shí)參必須為普通變量的地址
- 2 形參必須為指針變量
- 3 在被調(diào)函數(shù)中,通過(guò) *形參名 = …… 的方式就可以修改主調(diào)函數(shù)相關(guān)變量的值
2 指針和數(shù)組
指針 和 一維數(shù)組
一維數(shù)組名:是個(gè)指針常量,存放的是一維數(shù)組第一個(gè)元素的地址。類(lèi)型為int *
數(shù)組名,是int *類(lèi)型
數(shù)組下標(biāo)和指針的關(guān)系
如果p是個(gè)指針變量,則p[i]永遠(yuǎn)等價(jià)于 *(p+i)
a[i] == *(a + i)
int型
&a[i] == &*(a + i) == a + i
int *型
然后,當(dāng)i = 0時(shí),那么
a[0] == *a
int型
&a[0] == &*(a) == a;
int *型
a != a[0]
a == &a[0]
確定一個(gè)一維數(shù)組需要幾個(gè)參數(shù)?
需要兩個(gè)參數(shù):數(shù)組第一個(gè)元素的地址 + 數(shù)組的長(zhǎng)度
指針變量的運(yùn)算
指針變量不能 + * /
如果兩個(gè)指針變量指向的是同一塊連續(xù)空間中的不同存儲(chǔ)單元,則這兩個(gè)指針變量才可以相減
一個(gè)指針變量,無(wú)論它指向的變量占幾個(gè)字節(jié),該指針變量本身只占4個(gè)字節(jié)(32位下)
一個(gè)變量的地址,是使用該變量的首字節(jié)地址來(lái)表示的
指針 和 二維數(shù)組
指針和函數(shù)
指針和結(jié)構(gòu)體
多級(jí)指針
動(dòng)態(tài)分配內(nèi)存
傳統(tǒng)數(shù)組的缺點(diǎn):
- 數(shù)組的長(zhǎng)度必須事先制定,且只能是常整數(shù),不能是變量
int a[5];//OK
int len = 5; int a[len];//error - 傳統(tǒng)形式定義的數(shù)組,該數(shù)組的內(nèi)存程序員無(wú)法手動(dòng)釋放
在一個(gè)函數(shù)運(yùn)行期間,系統(tǒng)為該函數(shù)中數(shù)組所分配的空間會(huì)一直存在,直到該函數(shù)運(yùn)行完畢時(shí),數(shù)組的空間才會(huì)被系統(tǒng)釋放 - 數(shù)組的長(zhǎng)度不能在函數(shù)運(yùn)行過(guò)程中動(dòng)態(tài)的擴(kuò)充或縮小。
- A函數(shù)定義的數(shù)組在A函數(shù)運(yùn)行期間,可以被其他函數(shù)使用。但A函數(shù)運(yùn)行完畢之后,A函數(shù)中的數(shù)組將無(wú)法再被其他函數(shù)使用
為什么需要?jiǎng)討B(tài)內(nèi)存分配
動(dòng)態(tài)數(shù)組很好的解決了傳統(tǒng)數(shù)組的這4個(gè)缺陷(傳統(tǒng)數(shù)組 即 靜態(tài)數(shù)組)
動(dòng)態(tài)內(nèi)存分配舉例:動(dòng)態(tài)數(shù)組的構(gòu)造
靜態(tài)內(nèi)存和動(dòng)態(tài)內(nèi)存的比較
靜態(tài)內(nèi)存是由系統(tǒng)自動(dòng)分配,由系統(tǒng)自動(dòng)釋放
靜態(tài)內(nèi)存是在棧分配的
動(dòng)態(tài)內(nèi)存是由程序員手動(dòng)分配,手動(dòng)釋放
動(dòng)態(tài)內(nèi)存是在堆(是指堆排序)中分配的
結(jié)構(gòu)體
參考:C語(yǔ)言知識(shí)點(diǎn)—結(jié)構(gòu)體
進(jìn)制間轉(zhuǎn)換
已知十進(jìn)制求二進(jìn)制
-
求正整數(shù)的二進(jìn)制:除2取余,直至商為零,余數(shù)倒敘排序
-
求負(fù)整數(shù)的二進(jìn)制:
先求與該負(fù)數(shù)相對(duì)應(yīng)的正整數(shù)的二進(jìn)制代碼,然后將所有位取反,末尾加1,不夠位數(shù)時(shí),左邊補(bǔ)1
例:-3。其正整數(shù)3的二進(jìn)制代碼是011,取反,100,末尾加1,101。因?yàn)檎麛?shù)4個(gè)字節(jié),是4*8=32位,而101只占3位,其余29位都補(bǔ)成1。 -
求零的二進(jìn)制:全是零
已知二進(jìn)制求十進(jìn)制
- 如果首位是0,則表明是正整數(shù),按普通方法來(lái)求
- 如果首位是1,則表明是負(fù)整數(shù):將所有位取反,末尾加1,所得數(shù)字就是該負(fù)數(shù)的絕對(duì)值
- 如果全是零,則對(duì)應(yīng)的十進(jìn)制數(shù)字就是零
位運(yùn)算符:& | ~ ^ << >>
通過(guò)位運(yùn)算符,我們可以對(duì)數(shù)據(jù)的操作精確到每一位
& 按位與
| 按位或
~ 按位取反:把變量所有二進(jìn)制取反
^ 按位異或:相同為0;不同為1
1^0=1 0^1 = 1
1^1= 0 0^0 = 0
<<
按位左移
>>
按位右移
十進(jìn)制123,左移一位,成了1230,相當(dāng)于乘10
十進(jìn)制123,右移一位,成了12.3,相當(dāng)于除10
同理,二進(jìn)制左移1位相當(dāng)于乘2;右移1位相當(dāng)于除2;左移n位,相當(dāng)于乘以2n
C程序測(cè)試題
1 什么叫分配內(nèi)存,什么叫釋放內(nèi)存?
操作系統(tǒng)把某一塊內(nèi)存空間的使用權(quán)利分配給該程序 叫分配內(nèi)存
操作系統(tǒng)把分配給該程序的內(nèi)存空間的使用權(quán)利收回,改程序就不能夠再使用這一塊內(nèi)存空間,這叫釋放內(nèi)存
ps:釋放內(nèi)存不是把該內(nèi)存的內(nèi)容清零
2 變量為什么必須初始化?
不初始化,則變量通常就是垃圾值
3 靜態(tài)變量與動(dòng)態(tài)變量的異同?
相同:都需要分配內(nèi)存
不同:
靜態(tài)變量是由系統(tǒng)自動(dòng)分配,自動(dòng)釋放;
靜態(tài)變量是在棧中分配的
函數(shù)終止后,靜態(tài)變量的存儲(chǔ)空間被系統(tǒng)自動(dòng)釋放
動(dòng)態(tài)變量是由程序員手動(dòng)分配,手動(dòng)釋放;
動(dòng)態(tài)變量是在堆中分配的
程序員可以在函數(shù)執(zhí)行的過(guò)程中的任何一個(gè)時(shí)刻手動(dòng)釋放動(dòng)態(tài)變量的空間,不需要等到函數(shù)終止時(shí)才釋放
4 判斷下列程序語(yǔ)法上是否有錯(cuò)誤
A int *p; *p = 10; 錯(cuò)
B char *p; char ch = A; p = &ch; 對(duì) 錯(cuò) char ch = ‘A’;
C int i,j; i=j=0; int *p; p=&i; 對(duì)
D int *p; int **q; q=&p; 對(duì)
E int *p; int i = 5; p=&i; *p = 10; 對(duì)
二進(jìn)制全部為零的含義 —000000000000的含義
1 數(shù)值零
2 字符串結(jié)束標(biāo)記符’\0’
3 空指針NULL
NULL本質(zhì)也是零,但這個(gè)零不代表數(shù)字零,而表示的是內(nèi)存單元的編號(hào)零(是個(gè)地址)
計(jì)算機(jī)規(guī)定:以零為編號(hào)的存儲(chǔ)單元的內(nèi)容不可讀、不可寫(xiě)