一椎镣、簡述
對(duì)于C語言基礎(chǔ)相關(guān)方面的表面理解,簡單介紹兽赁。
二、二進(jìn)制
生活中常用的是十進(jìn)制冷守,基數(shù)0,1,2,3,4,5,6,7,8,9,刀崖。滿10進(jìn)1。
時(shí)鐘60進(jìn)制拍摇×燎眨基數(shù)0,1,2...57,58,59。滿60進(jìn)1充活。60秒為1分鐘蜂莉,60分鐘為1小時(shí)蜡娶。
計(jì)算機(jī)二進(jìn)制,基數(shù)0,1映穗。滿2進(jìn)1窖张。高電平代表1,低電平代表0蚁滋。計(jì)算機(jī)的指令和數(shù)據(jù)都是用0和1來表示的宿接。
三、計(jì)算機(jī)部分組成
CPU+內(nèi)存+外存辕录。
CPU執(zhí)行指令睦霎,CPU包括運(yùn)算器、控制器走诞。(包括多個(gè)寄存器)運(yùn)算器負(fù)責(zé)邏輯運(yùn)算副女,控制器包括對(duì)數(shù)據(jù)和指令的存取操作。
內(nèi)存運(yùn)行當(dāng)前的程序(代碼+數(shù)據(jù))蚣旱,(代碼可以看做是一系列的指令)內(nèi)存可以劃分為很多個(gè)單元碑幅,每個(gè)單元一個(gè)字節(jié)并對(duì)應(yīng)一個(gè)編號(hào),這個(gè)編號(hào)稱為地址。(斷電了就數(shù)據(jù)沒了)
外存可以簡單認(rèn)為是硬盤姻锁。(存放數(shù)據(jù)枕赵、應(yīng)用程序等,斷電了數(shù)據(jù)還在)
程序運(yùn)行:程序test.exe放在硬盤位隶,CPU將test.exe讀取到內(nèi)存拷窜,然后逐條執(zhí)行指令。
多任務(wù):有多個(gè)程序在同時(shí)運(yùn)行涧黄,但是只有一個(gè)CPU篮昧,采用時(shí)間片輪詢方式,簡單來說笋妥,假設(shè)A,B,C三個(gè)程序同時(shí)執(zhí)行懊昨,CPU執(zhí)行A程序的一條指令,然后再執(zhí)行B程序的一條指令春宣,再執(zhí)行C程序的一條指令酵颁,再到A。CPU執(zhí)行得很快月帝,看起來是同時(shí)執(zhí)行的躏惋。當(dāng)然任務(wù)之間還有優(yōu)先級(jí)。
斷電數(shù)據(jù)丟失:在內(nèi)存中的數(shù)據(jù)都是用電來表示的嚷辅,斷電之后簿姨,這些數(shù)據(jù)就會(huì)丟失。
虛擬內(nèi)存:操作系統(tǒng)為了更好、更高效地使用內(nèi)存扁位,管理內(nèi)存准潭,將實(shí)際物理內(nèi)存進(jìn)行了映射,對(duì)應(yīng)用程序屏蔽了物理內(nèi)存的細(xì)節(jié)域仇,有利簡化程序的編寫刑然。假設(shè)物理內(nèi)存只有1G,有三個(gè)應(yīng)用程序同時(shí)在運(yùn)行殉簸,系統(tǒng)會(huì)將物理內(nèi)存的一部分映射為3個(gè)大小均為4G的虛擬內(nèi)存闰集,讓每一個(gè)應(yīng)用程序都以為自己擁有4G內(nèi)存(實(shí)際并不是,虛擬內(nèi)存經(jīng)過一定的方式映射為物理內(nèi)存)般卑,這樣極大地方便了應(yīng)用程序的數(shù)據(jù)和代碼的組織武鲁。
內(nèi)存4區(qū):棧區(qū),堆區(qū)蝠检,全局區(qū)沐鼠,代碼區(qū)。
總線:計(jì)算機(jī)各部分通過總線連接叹谁。包括地址總線饲梭,數(shù)據(jù)總線,控制總線焰檩。地址總線:比如有32根地址總線憔涉,每一根線有高電平1,低電平兩種狀態(tài)0析苫,那么可以表示0x00000000~0xFFFFFFFF總共2的32次方這么多個(gè)地址兜叨,一個(gè)地址可以表示一個(gè)內(nèi)存單元。一般來說衩侥,地址總線越多国旷,可以表示的地址越多。指針變量就是存放地址的茫死,比如:int i = 10; int *p = &i;若i的地址為0x00800400;那么p指針變量存放的值就是0x00800400跪但,是一個(gè)有實(shí)際地址意義的整數(shù)。因?yàn)槭?2根地址總線峦萎,所以sizeof(p) = 4 (字節(jié))屡久。數(shù)據(jù)總線:比如有8根數(shù)據(jù)線,那么同時(shí)可以存取8位數(shù)據(jù)爱榔,一般來說數(shù)據(jù)總線越多涂身,同時(shí)存取的數(shù)據(jù)越多,執(zhí)行效率越高搓蚪。控制總線:控制丁鹉、協(xié)調(diào)計(jì)算機(jī)各部分工作妒潭,存取指令悴能。一般來說總線還可以拓展。
四雳灾、變量
內(nèi)存分為一個(gè)一個(gè)單元漠酿,一個(gè)單元一個(gè)字節(jié),并且一個(gè)單元對(duì)應(yīng)一個(gè)地址編號(hào)谎亩。
在匯編語言中炒嘲,可以直接對(duì)內(nèi)存地址進(jìn)行操作,如:MOV AL,[2000H] ;將內(nèi)存地址0x2000的內(nèi)容送到AL寄存器中匈庭。
匯編中夫凸,直接將數(shù)據(jù)存放到某個(gè)內(nèi)存地址,如將學(xué)生學(xué)號(hào)放到某個(gè)地址阱持,學(xué)生姓名放到某個(gè)地址夭拌。到時(shí)候讀取的時(shí)候,直接讀取某個(gè)地址衷咽。這樣子固然程序執(zhí)行效率高鸽扁,但是如果數(shù)據(jù)一多,難免會(huì)記不住哪個(gè)數(shù)據(jù)對(duì)應(yīng)哪個(gè)地址镶骗,看到一個(gè)地址桶现,自己還得想一下之前這個(gè)地址(這一段內(nèi)存)存放的是什么數(shù)據(jù),寫起代碼也不方便鼎姊。時(shí)間一長骡和,就算是自己編寫的代碼都要花很多時(shí)間才能看懂,而且維護(hù)起來也比較麻煩此蜈。
這樣我們將數(shù)據(jù)對(duì)應(yīng)的一段內(nèi)存起一個(gè)名字即横,這個(gè)名字就代表著一片內(nèi)存,到時(shí)候直接操作著個(gè)名字就相當(dāng)于操作這一片內(nèi)存裆赵,這個(gè)名字就是我們所說的變量东囚。起一個(gè)與數(shù)據(jù)相關(guān)的有意義的名字,方便我們編程战授。如:C語言中页藻,我們可以將存放學(xué)生學(xué)號(hào)的那一段內(nèi)存叫做id,將存放學(xué)生姓名的那一段內(nèi)存叫做name。這樣我們就可以通過id植兰,name這兩個(gè)變量名類讀取或存儲(chǔ)學(xué)生的id信息和姓名信息份帐,到時(shí)候我們一看變量名name,我們就能想到這是存放姓名信息的楣导。
變量:對(duì)應(yīng)一片內(nèi)存废境,內(nèi)存可以存放不同的數(shù)據(jù),變量,變化的量噩凹。變量的地址就是對(duì)應(yīng)的那一片內(nèi)存首地址巴元。如果變量占據(jù)多個(gè)內(nèi)存單元,首個(gè)內(nèi)存單元的地址就是變量的地址驮宴。程序中定義一個(gè)變量就在內(nèi)存中開辟一片內(nèi)存空間(系統(tǒng)為程序分配一片內(nèi)存空間逮刨,如int i = 0;在32位系統(tǒng)中堵泽,系統(tǒng)會(huì)分配4字節(jié)的內(nèi)存空間修己,在單片機(jī)中就可能是在RAM中分配2字節(jié)(16位) )。
五迎罗、數(shù)據(jù)類型
為了方便睬愤,或者是為了執(zhí)行效率,計(jì)算機(jī)采用了二進(jìn)制佳谦,通過低電平或斷電狀態(tài)表示0戴涝,通過 通電或高電平狀態(tài)表示1。這樣一來钻蔑,計(jì)算機(jī)只認(rèn)識(shí)0和1啥刻,也只能表示0和1。那么我需要表示其他數(shù)字:2咪笑,3可帽,4....字符:a,b,c...怎么辦?我們可以使用多個(gè)0和1來代表其他數(shù)字和字符窗怒,并統(tǒng)一為一個(gè)表映跟。
....... | ....... |
---|---|
00110000 | 數(shù)字0 |
00110001 | 數(shù)字1 |
00110010 | 數(shù)字2 |
........ | ....... |
01000100 | 大寫字母D |
01000101 | 大寫字母E |
........ | ........ |
在內(nèi)存中,表達(dá)整數(shù)0我們可以用 00110000扬虚,表達(dá)整數(shù)4億我們可以用 00111111100011000011110努隙。
上面這樣子表示,我們可以知道這一段的0和1表示這整數(shù)0辜昵,那一段0和1表示4億荸镊,但是實(shí)際上我們“看”不到內(nèi)存,我們不知道從這個(gè)位置開始堪置,到哪里結(jié)束表示著一個(gè)數(shù)據(jù)躬存。我們需要明確規(guī)定多少個(gè)0和1表示一個(gè)整數(shù),假設(shè)我們約定8位0和1表示一個(gè)整數(shù)舀锨,這樣我們知道了內(nèi)存首地址岭洲,往后讀取8個(gè)0和1然后就可以讀取到一個(gè)數(shù)據(jù)(整數(shù))。就像加密的電報(bào)一樣坎匿,"滴滴"表示1盾剩,“滴”表示0雷激。按照多少個(gè)0和1代表一個(gè)字,才能正確的解密彪腔。
所以我們需要指定多少個(gè)0和1來表示一個(gè)數(shù)據(jù)侥锦。8個(gè)0和1可以表示2的8次方==〉256個(gè)數(shù)。要是有正負(fù)值德挣,表示范圍為-128-127。比如在32位系統(tǒng)中快毛,C語言的整型int用32位即4字節(jié)表示格嗅,可以表示2的32次方==〉4294967296個(gè)數(shù),有符號(hào)的表示范圍為-2147483648——2147483647唠帝。有一些數(shù)據(jù)范圍不大屯掖,只需幾十個(gè),如果用32位表示一個(gè)數(shù)據(jù)就顯得浪費(fèi)內(nèi)存襟衰。有一些數(shù)據(jù)范圍很大贴铜,用32位表示又不夠表示,于是就有16位的short類型瀑晒,64位的long long類型(不同的系統(tǒng)有可能類型的位數(shù)不一樣)绍坝。就像用盒子打包物品一樣,有一些物品比較小苔悦,有一些物品比較大轩褐。要是統(tǒng)一用一種尺寸的盒子裝,盒子過小玖详,大的物品又裝不下把介,盒子過大,用來裝小的有顯得有點(diǎn)浪費(fèi)蟋座,于是多種尺寸的盒子就產(chǎn)生了-多種數(shù)據(jù)類型拗踢。還有一個(gè)原因:就是在表達(dá)小數(shù),或者是非常大的數(shù)時(shí)就算是64位也有點(diǎn)無能為力向臀,但是如果改變存儲(chǔ)方式巢墅,同樣是64位,卻可以表示更大范圍的數(shù)飒硅。于是有了新的數(shù)據(jù)存儲(chǔ)方式砂缩,這是針對(duì)浮點(diǎn)數(shù)的。(如果將整數(shù)和浮點(diǎn)數(shù)采用同樣的存儲(chǔ)方式三娩,計(jì)算機(jī)結(jié)構(gòu)會(huì)更加復(fù)雜化庵芭,甚至?xí)档蛨?zhí)行效率)
數(shù)據(jù)的大小范圍不一,整數(shù)雀监,浮點(diǎn)數(shù)的存儲(chǔ)方式不一樣(讀取的時(shí)候解析的方式也不一樣)双吆,為了合理利用內(nèi)存眨唬,提高執(zhí)行效率,方便開發(fā)等原因好乐,我們需要不同的數(shù)據(jù)類型匾竿。
不同的數(shù)據(jù)類型意味著數(shù)據(jù)的大小不同(多少位0和1表示一個(gè)數(shù)據(jù),也就是這種數(shù)據(jù)類型占多少個(gè)字節(jié))蔚万,數(shù)據(jù)的存儲(chǔ)方式(數(shù)據(jù)的解析方式)不同岭妖。也就是說同一個(gè)內(nèi)存首地址,按照不同的數(shù)據(jù)類型反璃,即按照不同的位數(shù)解讀內(nèi)存數(shù)據(jù)昵慌,就會(huì)讀取出不一樣的數(shù)據(jù),按照不同的解析方式淮蜈,也會(huì)讀取出不一樣的數(shù)據(jù)斋攀。就像加密電報(bào)一樣,按照不同的位數(shù)一樣的譯碼表也會(huì)解讀出不一樣的譯文梧田,按照一樣的位數(shù)不一樣的譯碼表也會(huì)解讀出不一樣的數(shù)據(jù)淳蔼。如果僅僅知道數(shù)據(jù)的地址,不知道數(shù)據(jù)類型(包含數(shù)據(jù)大小裁眯、數(shù)據(jù)的解析方式)鹉梨,是無法正確解讀數(shù)據(jù)的。如有一數(shù)據(jù)的首地址是0x0F48000,從這個(gè)地址開始存儲(chǔ)著:10100011010101110100010100001011101000111011010010000101010100000101001100001010010010010110101010011
不知道數(shù)據(jù)類型未状,那么到哪里結(jié)束才是整個(gè)數(shù)據(jù)俯画?就算知道了到哪里結(jié)束,又該怎么解析司草?(要知道還有用戶構(gòu)造類型--結(jié)構(gòu)體類型)艰垂。因此,用地址操作數(shù)據(jù) 需要配合數(shù)據(jù)類型埋虹。
定義不同數(shù)據(jù)類型的變量猜憎,系統(tǒng)根據(jù)數(shù)據(jù)類型分配相應(yīng)的內(nèi)存大小,程序填充數(shù)據(jù)時(shí)根據(jù)相應(yīng)的存儲(chǔ)方式搔课,讀取數(shù)據(jù)時(shí)按照相應(yīng)的方式解析胰柑,不然讀取不到正確的數(shù)據(jù)。如float類型的數(shù)據(jù)爬泥,如果直接按照int類型數(shù)據(jù)讀取柬讨,那么讀取出來的不是正確的數(shù)據(jù)。如float類型的數(shù)據(jù)12.0袍啡,如果按照int類型數(shù)據(jù)解讀踩官,就得不到我們"期望"的12。
int類型存放整數(shù)境输,char類型存放字符蔗牡,float類型存放浮點(diǎn)數(shù)颖系,那么有沒有一種變量是存放地址的呢?當(dāng)然有--指針辩越。
在32位系統(tǒng)環(huán)境嘁扼,一般來說指針變量大小就是32位(4字節(jié)),那么為什么還有指針的數(shù)據(jù)類型呢黔攒?因?yàn)槲覀冎酪粋€(gè)內(nèi)存首地址以及數(shù)據(jù)大小趁啸,還需要確定怎么解析數(shù)據(jù),類型就是用來指示解析/存儲(chǔ)數(shù)據(jù)的亏钩。
六莲绰、修改內(nèi)存數(shù)據(jù)
對(duì)于程序自己申請的內(nèi)存,作為擁有者姑丑,可以對(duì)這一片內(nèi)存進(jìn)行讀取或修改數(shù)據(jù),其他程序一般沒有權(quán)限讀取或修改辞友。但是可以通過一些方式可以進(jìn)行修改栅哀。
七、發(fā)展歷史称龙,應(yīng)用場景留拾,編譯器
對(duì)于發(fā)展歷史,就有必要提及兼容性鲫尊,和各種名詞的由來痴柔。
有時(shí)候我們會(huì)有這種疑惑,為什么這樣子設(shè)計(jì)疫向,為什么不能簡單一點(diǎn)呢咳蔚?
有可能是為了兼容以前的版本,或者是預(yù)留拓展接口搔驼。
有時(shí)候我們會(huì)有這種疑惑谈火,為什這樣子命名?一點(diǎn)都不形象舌涨。
有可能是它原來就很形象的糯耍,只是它被改進(jìn)了。就像剛接觸電腦時(shí)囊嘉,感慨電腦的功能真是強(qiáng)大温技,不愧"電腦"之稱。
為什么會(huì)被叫做計(jì)算機(jī)呢扭粱?因?yàn)樗緛碜畛踉O(shè)計(jì)的時(shí)候舵鳞,它就是一臺(tái)只會(huì)計(jì)算的機(jī)器晰绎。(原理上凝果,它的核心也只會(huì)計(jì)算)
了解一樣?xùn)|西的發(fā)展過程,或者說了解一樣?xùn)|西的創(chuàng)造過程、改進(jìn)過程豆赏。
可以拓展我們的思維,可能在以后的創(chuàng)造和設(shè)計(jì)中不知不覺的就進(jìn)行模仿躬它,參照比較荚醒。
關(guān)于應(yīng)用場景,就有必要談及優(yōu)缺點(diǎn)霜旧,有優(yōu)勢才有"前途"错忱。
(也許是意外的"接觸"到C語言,但是如果想要深入學(xué)習(xí)的話挂据,就有必要了解它究竟能"做什么")
編譯器:將我們編輯的代碼翻譯為計(jì)算機(jī)所"認(rèn)識(shí)"的機(jī)器代碼以清。
(這個(gè)機(jī)器代碼:或者說計(jì)算機(jī)指令,可以簡單認(rèn)為是我們預(yù)定義的動(dòng)作代號(hào))
有時(shí)候編譯器不會(huì)聽話崎逃,不會(huì)按照我們的代碼一成不變的"翻譯"掷倔,它還會(huì)"做手腳"。
比如有一些編譯器會(huì)對(duì)代碼進(jìn)行優(yōu)化个绍,如:
int i;
int j;
for(i=0; i<200; i++) {
for(j=0; j<102; j++);
}
編譯器發(fā)現(xiàn)循環(huán)里面什么都沒做勒葱,它就會(huì)將這一段代碼,去掉巴柿,
然后再發(fā)現(xiàn)凛虽,i,j都沒有使用,又將定義i广恢,j的語句去掉凯旋。
有時(shí)候,我們就是想通過這樣來實(shí)現(xiàn)一定的延時(shí)呢钉迷?
別擔(dān)心至非,一般的編譯器不會(huì)默認(rèn)優(yōu)化,而且可以設(shè)置是否優(yōu)化以及優(yōu)化的級(jí)別篷牌。
編譯器會(huì)幫我們分析詞法睡蟋、語法。不同的版本有差異枷颊,或者說它支持的標(biāo)準(zhǔn)不同戳杀。
如C99標(biāo)準(zhǔn)的支持如下格式:
for(int i=0; i<200; i++) {}
C89就不支持了。
編譯器參照的標(biāo)準(zhǔn)不一樣夭苗,寫法就可能存在差異信卡。
平臺(tái)的差異(Windows, Linux...),寫法就可能存在差異题造。
八傍菇、待整理待補(bǔ)充
1、碼(ASCII碼界赔,原碼丢习,反碼牵触,補(bǔ)碼。咐低。揽思。) 字符、負(fù)數(shù)的存儲(chǔ)方式见擦。
2钉汗、基本數(shù)據(jù)類型(char, int, float, double, long。鲤屡。损痰。) 了解其大小,存儲(chǔ)/解析方式酒来,數(shù)值的表示范圍卢未。(數(shù)值溢出回繞)
3、關(guān)鍵字堰汉,變量 變量的命名方式
4尝丐、運(yùn)算符 算術(shù)運(yùn)算符(+-*/),邏輯運(yùn)算符(&&,||,!)衡奥、關(guān)系運(yùn)算符(>,<,=),運(yùn)算符結(jié)合性远荠、優(yōu)先級(jí)矮固。。譬淳。)
5档址、表達(dá)式 算數(shù)表達(dá)式,邏輯表達(dá)式邻梆,關(guān)系表達(dá)式, 逗號(hào)表達(dá)式守伸。。浦妄。
6尼摹、控制結(jié)構(gòu) if-else、switch剂娄、for蠢涝、while、do-while阅懦、goto和二;(break與continue)
7、函數(shù) 函數(shù)調(diào)用過程耳胎、遞歸惯吕、變參函數(shù)惕它、內(nèi)聯(lián)函數(shù)
8、數(shù)組 數(shù)組特點(diǎn)废登、數(shù)組嵌套
9淹魄、指針 指針含義、指針操作钳宪、多級(jí)指針揭北,指針與數(shù)組
10、文件操作 讀寫吏颖、增刪改查搔体、文本文件、二進(jìn)制文件
11半醉、內(nèi)存布局 內(nèi)存堆疚俱、棧、全局區(qū)缩多、代碼區(qū)
12呆奕、組合數(shù)據(jù)類型 結(jié)構(gòu)體(內(nèi)存對(duì)齊)、共用體衬吆、枚舉
13梁钾、字符串操作、編譯過程逊抡、頭文件姆泻、宏定義、條件編譯冒嫡、定義聲明拇勃、變量的生命周期、作用域孝凌、可見域
14方咆、數(shù)據(jù)結(jié)構(gòu) 鏈表(單向鏈表,循環(huán)鏈表蟀架,雙向鏈表)瓣赂、堆、棧辜窑、樹(二叉樹钩述、平衡二叉樹、紅黑樹)
15穆碎、線程牙勘、進(jìn)程 并發(fā)任務(wù)、線程鎖
16、網(wǎng)絡(luò)編程 TCP方面、UDP放钦,網(wǎng)絡(luò)字節(jié)序(字節(jié)序:大端序、小端序)
內(nèi)存對(duì)齊:為了提高CPU的訪問效率(存取數(shù)據(jù)的速度)恭金,編譯器會(huì)對(duì)數(shù)據(jù)進(jìn)行字節(jié)對(duì)齊操禀。
(這種對(duì)齊設(shè)置可以簡化 CPU 和內(nèi)存 RAM 之間的接口和硬件設(shè)計(jì)。比如一個(gè)32位的機(jī)器横腿,CPU 讀取內(nèi)存時(shí)颓屑,硬件設(shè)計(jì)上可能只支持4字節(jié)對(duì)齊的地址訪問)
地址線、數(shù)據(jù)線的條數(shù)決定CPU一次最大能夠同時(shí)存取訪問多少字節(jié)的數(shù)據(jù)耿焊。
在32位機(jī)器中揪惦,CPU一次最大能夠同時(shí)存取訪問32位(4字節(jié))數(shù)據(jù),一般數(shù)據(jù)都大于4字節(jié)罗侯,為了加快CPU存取效率器腋,
CPU每次都取4字節(jié)(無論數(shù)據(jù)有沒有4字節(jié),CPU都會(huì)取出來4字節(jié))钩杰。