C語言內(nèi)存這個話題-創(chuàng)新互聯(lián)

1、計算機(jī)為什么需要編程?編程已經(jīng)編了這么多年,已經(jīng)寫了很多程序,為什么還需要編程?

網(wǎng)站的建設(shè)創(chuàng)新互聯(lián)專注網(wǎng)站定制,經(jīng)驗(yàn)豐富,不做模板,主營網(wǎng)站定制開發(fā).小程序定制開發(fā),H5頁面制作!給你煥然一新的設(shè)計體驗(yàn)!已為成都宴會酒店設(shè)計等企業(yè)提供專業(yè)服務(wù)。

因?yàn)槲覀冃枰ㄏM┩ㄟ^程序,達(dá)到一定的目的或者得到一定的結(jié)果。

編寫新的程序是為了得到不同的結(jié)果。

計算機(jī)程序 = 代碼 + 數(shù)據(jù) (經(jīng)過運(yùn)行后得到一個結(jié)果,就是計算機(jī)程序運(yùn)行的結(jié)果)

從宏觀上理解:代碼就是動作,就是加工數(shù)據(jù)指令。

 數(shù)據(jù)就是數(shù)字,就是我們希望被代碼加工的數(shù)字。

結(jié)論:計算機(jī)編程不外乎兩種目的,結(jié)果或者過程;即加工數(shù)據(jù)得到結(jié)果。

可以用函數(shù)來類比:比如函數(shù)的形參就是待加工的數(shù)據(jù)(有可能函數(shù)內(nèi)還需要一些臨時數(shù)據(jù),就是局部變量),函數(shù)體就是代碼,函數(shù)體的執(zhí)行就是加工過程,函數(shù)的返回值就是結(jié)果

2、程序就是有很多個函數(shù)組成的,函數(shù)是程序的重要組成部分。

程序需要運(yùn)行才會得到我們需要的結(jié)果或者過程。

程序的本質(zhì)就是函數(shù),函數(shù)的本質(zhì)是加工數(shù)據(jù)的動作。

3、馮諾依曼結(jié)構(gòu)和哈佛結(jié)構(gòu)

馮諾依曼結(jié)構(gòu)是:數(shù)據(jù)和代碼放在一起。

哈佛結(jié)構(gòu)是:數(shù)據(jù)和代碼分開存在。

什么是代碼:函數(shù)

什么是數(shù)據(jù):全局變量、局部變量

譬如在S5PV210中運(yùn)行的linux系統(tǒng)上,運(yùn)行應(yīng)用程序時:這時候所有的應(yīng)用程序的代碼和數(shù)據(jù)都在DRAM,所以這種結(jié)構(gòu)就是馮諾依曼結(jié)構(gòu);

在單片機(jī)中,我們把程序代碼燒寫到Flash(內(nèi)置NorFlash,flash是只讀的)中,然后程序在Flash中原地運(yùn)行,程序中所涉及到的數(shù)據(jù)(全局變量、局部變量)不能放在Flash中,必須放在RAM(SRAM)中。這種就叫哈佛結(jié)構(gòu)。

4、動態(tài)內(nèi)存DRAM和靜態(tài)內(nèi)存SRAM

靜態(tài)內(nèi)存是系統(tǒng)分給一定的內(nèi)存后不再變化了,也就是在程序一開始運(yùn)行就分配內(nèi)存(不需要初始化就可以直接使用的),直到程序結(jié)束了,內(nèi)存才被釋放;

動態(tài)內(nèi)存是系統(tǒng)開始不分配內(nèi)存,運(yùn)行時根據(jù)需要分配(需要先進(jìn)行初始化才能進(jìn)行使用),也就是在程序調(diào)用在程序中定義的函數(shù)時才被分配,函數(shù)調(diào)用結(jié)束了,內(nèi)存就釋放

5、為什么需要內(nèi)存?

總結(jié):內(nèi)存是用來存儲可變數(shù)據(jù)的,數(shù)據(jù)在程序中表現(xiàn)為全局變量或局部變量等(在gcc中,常量也是存儲在內(nèi)存中;但在大部分單片機(jī)中,常量存儲在flash中的,也就是代碼段中)

很多編程的關(guān)鍵都是為了內(nèi)存,譬如數(shù)據(jù)結(jié)構(gòu)和算法

數(shù)據(jù)結(jié)構(gòu)是研究數(shù)據(jù)如何組織的,而數(shù)據(jù)是放在內(nèi)存中的。

算法是研究如何更優(yōu)秀的更有效的加工數(shù)據(jù),也離不開內(nèi)存。衡量一個算法優(yōu)秀與否,絕大部分與這個算法所占的內(nèi)存大小有關(guān)

。

6、如何管理內(nèi)存?

內(nèi)存是程序的一種資源,不能過于或隨便的浪費(fèi)。所以管理內(nèi)存對程序來說是一種很重要的技術(shù)。

在沒有操作系統(tǒng)(也就是裸機(jī)程序)中,程序需要直接操作內(nèi)存,編程者需要自己計算內(nèi)存的使用和安排,如果不小心把內(nèi)存用錯了,后果需要自己承擔(dān)。

從語言角度來講:不同的語言提供了不同的內(nèi)存操作接口;

譬如匯編:根本沒有任何內(nèi)存管理,內(nèi)存管理全靠程序員自己,匯編中操作內(nèi)存時直接使用內(nèi)存地址(如0xd0020010),非常麻煩。

譬如C語言:C語言中編譯器幫我們管理直接內(nèi)存地址,我們都是通過編譯器提供的變量名等來訪問內(nèi)存的。在操作系統(tǒng)中,如果需要大塊內(nèi)存,可以通過API(malloc分配內(nèi)存free釋放內(nèi)存)來訪問系統(tǒng)內(nèi)存;在裸機(jī)系統(tǒng)中,如果需要大塊的內(nèi)存,就需要自己來定義數(shù)組等解決

總結(jié):語言沒有好壞,只有適應(yīng)不適應(yīng);譬如當(dāng)我們程序?qū)π阅埽ㄈ绮僮飨到y(tǒng)內(nèi)核)非常需要時就會使用C/C++,當(dāng)我們對開發(fā)程序速度非常需要時,就會使用java/C#

7、什么是內(nèi)存?

內(nèi)存(RAM)從硬件上講就是一個電腦配件(內(nèi)存條)。

從邏輯上講內(nèi)存是一種這樣的東西,可以隨機(jī)訪問,隨時進(jìn)行讀寫(也可以限制只讀或者只寫)。

內(nèi)存在 編程中天生就是為存放變量的(也可以說就是有了內(nèi)存,才有了C語言的變量,原來受限于硬件)

內(nèi)存實(shí)際是有無數(shù)個內(nèi)存單元格組成的,每一個單元格都有一個唯一的內(nèi)存地址

用大樓來類比內(nèi)存很合適,內(nèi)存就像是一棟無限高的大樓,一個個內(nèi)存單元格就像是大樓內(nèi)的一個個小房子,內(nèi)存地址就像是門牌號,存進(jìn)去的內(nèi)容就像是住進(jìn)去的人

8、位,字節(jié),半字,字的概念和內(nèi)存位寬

內(nèi)存單元的大小單位:位(1bit) 字節(jié)(8bit) 半字(一般是16bit)  字(一般是32bit)

在所有計算機(jī),所有操作系統(tǒng)中,位永遠(yuǎn)是 1bit,字節(jié)永遠(yuǎn)是 8bit

歷史上曾經(jīng)出現(xiàn)過16位,32位,64位系統(tǒng)三種,而且系統(tǒng)還有windows,linux,ios等。半字和字等很多概念被混亂定義過

所以在工作中不要詳細(xì)區(qū)分字,半字,雙子的概念,只要知道這些單位具體占多少位是依賴于平臺的,實(shí)際工作中先去搞清楚所在平臺的定義,需要注意的是半字一定是字的一半,雙字一定是字的2倍

編程一般用不到字的概念,區(qū)分主要是我們會在文檔中用到字,如果不加區(qū)分,容易造成理解錯誤

在linux+ARM的平臺上  字是32位的

內(nèi)存芯片之間可以并聯(lián),即使是8位的內(nèi)存芯片,通過并聯(lián)可以也可以做出來16位,32位的內(nèi)存芯片

9、內(nèi)存編址和尋址、內(nèi)存對齊

內(nèi)存在邏輯上就是一個一個的格子(內(nèi)存單元格),里面可以存儲數(shù)據(jù),每一個單元格都有一個內(nèi)存地址,單元格與內(nèi)存地址一一對應(yīng)且永久綁定,這就是內(nèi)存編址的方法

一個內(nèi)存單元有兩個概念:地址和空間(內(nèi)存單元的兩面性)

關(guān)鍵:內(nèi)存編址是以字節(jié)為單位的

一個內(nèi)存地址,對應(yīng)的空間(內(nèi)存單元)大小是一定的,就是一個字節(jié)(8bit)

內(nèi)存對齊;對齊訪問和硬件匹配,所以效率高,非對齊訪問和硬件不搭配,所以效率低(因?yàn)橄到y(tǒng)兼容性的問題,非對齊訪問也可以實(shí)現(xiàn))

10、數(shù)據(jù)類型和內(nèi)存的關(guān)系

數(shù)據(jù)類型是用來定義變量的,變量要存儲、運(yùn)算在內(nèi)存中,所以內(nèi)存就必須語相應(yīng)的數(shù)據(jù)類型相匹配,否則就會造成效率低下或者不工作

int ×××(整數(shù)類型,整的意思就是說和cpu本身的數(shù)據(jù)位寬(32位或64位)是一樣的)

C語言的數(shù)據(jù)類型決定一個內(nèi)存單元的長度和解析方法

類型只是對后面符號或者數(shù)字(代表的內(nèi)存地址)所表征的內(nèi)存長度規(guī)定和解析方法規(guī)定而已

指針全名是指針變量,實(shí)質(zhì)上和普通變量沒有任何區(qū)別(包括內(nèi)存分配)

11、內(nèi)存管理之結(jié)構(gòu)體

數(shù)據(jù)結(jié)構(gòu)就是研究數(shù)據(jù)如何組織(在內(nèi)存中分布)和加工的學(xué)問

最簡單的數(shù)據(jù)結(jié)構(gòu)就是數(shù)組(可以一次定義多個數(shù)據(jù)類型相同,意義相關(guān)的變量); //int a[10];

數(shù)組的優(yōu)點(diǎn):數(shù)組比較簡單,可以隨機(jī)訪問,訪問時用下標(biāo)

數(shù)組的缺點(diǎn):數(shù)組內(nèi)所有元素的類型必須相同,且在定義時數(shù)組大小就確定,而且不能改變(沒有伸縮性,靈活性差)

而在結(jié)構(gòu)體中可以定義數(shù)據(jù)類型不同的變量

struct number
{
int age;
char name[20];
double high;
};

結(jié)構(gòu)體可以說是數(shù)組的升級版;如果結(jié)構(gòu)體中的數(shù)據(jù)類型全都相同就可以用數(shù)組來代替;

結(jié)構(gòu)體內(nèi)嵌指針可以實(shí)現(xiàn)面向?qū)ο螅?/p>

總的來說C語言是面向程序的,但是C語言寫出的linux系統(tǒng)是面向?qū)ο蟮?/p>

struct s
{
int age;                //普通變量
void (*pFunc)(void);    //函數(shù)指針,指向 void func(void) 這類的函數(shù)
};

使用這樣的結(jié)構(gòu)體就可以實(shí)現(xiàn)面向?qū)ο?/p>

12、內(nèi)存管理之棧

什么是棧:棧是一種數(shù)據(jù)結(jié)構(gòu),C語言中用棧來存儲局部變量;棧是用來管理內(nèi)存的

棧:先進(jìn)后出;入口即出口,有一個口是堵死的,所以先進(jìn)去的必須后出來

隊(duì)列:先進(jìn)先出;入口和出口是分開的,必須從入口進(jìn),從出口出,所以先進(jìn)去的先出來

棧內(nèi)存是反復(fù)使用的,上次用完的值沒有清零,所以定義局部變量時需要顯式初始化,如果沒有顯式初始化,那么值就是隨機(jī)的。

13、復(fù)雜數(shù)據(jù)結(jié)構(gòu)

鏈表:最常用也是最重要的(在嵌入式開發(fā)領(lǐng)域)

14、位操作運(yùn)算

運(yùn)算種類和運(yùn)算符:

位與:符號 a&b 全一為一,有零為零 用于對關(guān)心位清零(和零作位與)

位或:符號 a|b 全零為零,有一為一 用于對關(guān)心位置位(置一,和一作位或)

位異或:符號a^b 相同為零,不同為一 用于對關(guān)心位取反(和一作異或)

位取反:符號 ~a 一變零,零變一

位左移:符號a<<

位右移:符號a>> 對于有符號數(shù),右移時左側(cè)補(bǔ)符號位(如果正數(shù)就補(bǔ)0,負(fù)數(shù)就補(bǔ)1,叫算術(shù)移位)

15、邏輯操作運(yùn)算

在C語言中,只有0為假,其他的全都是真

邏輯與:符號 a&&b 有假為假,全真為真

邏輯或:符號 a||b 有真為真,全假為假

邏輯取反:符號 !a 真變假,假變真

16、指針是C語言的精髓

指針變量和普通變量沒有任何本質(zhì)區(qū)別

標(biāo)準(zhǔn)用法: int a = 10, b = 0; int *p; p = &a; b = *p; //結(jié)果b = 10

16、野指針問題

野指針就是指定義后沒有初始化或者賦值的指針

野指針指向的位置是隨機(jī)的,是不可預(yù)知的,在運(yùn)行時容易觸發(fā)段錯誤(Sgmentation fault)

總結(jié):指針變量和普通局部變量一樣,都是存儲在棧上,都需要在定義時,進(jìn)行初始化,否則值就是隨機(jī)的

17、如何避免野指針問題

一般注意以下四點(diǎn)就可以避免野指針問題

第一點(diǎn):在定義指針變量時就初始化為NULL

第二點(diǎn):在解引用前判斷指針是否指向NULL(指向則不執(zhí)行解引用,不指向則可以放心解引用)

即  if(NULL != p);

第三點(diǎn):在解引用完成后,重新把指針賦值為NULL

第四點(diǎn):在解引用前確保指針指向一個確定的內(nèi)存地址(需要程序員自己把握)

NULL的實(shí)質(zhì)就是數(shù)字0,0地址是不可訪問的

18、const關(guān)鍵字和指針結(jié)合

const和指針常見的有四種方式:

第一種:int const *p; //p是一個指針,指向一個int型數(shù)據(jù),p所指向的是個常量

第二種:const int *p; //p是一個指針,指向一個int型數(shù)據(jù),p所指向的是個常量

第三種:int *const p; //p是一個指針,指向一個int型數(shù)據(jù),p本身是常量,指向的是變量

第四種:const int *const p; //p是一個指針,指向一個int型數(shù)據(jù),p本身是常量,指向的也是常量

關(guān)于指針變量,一共涉及到兩個變量,一個是指針變量本身(p),一個是指針?biāo)赶虻哪莻€變量(*p),而一個const關(guān)鍵字只能修飾一個變量。

19、深入學(xué)習(xí)數(shù)組

從內(nèi)存角度看,數(shù)組就是一次定義多個變量,而且在內(nèi)存中的存儲單元的內(nèi)存地址是依次連續(xù)的

從編譯器角度看,數(shù)組數(shù)組變量本質(zhì)上和普通變量,指針變量沒有區(qū)別;變量的本質(zhì)就是一個地址,編譯器把地址(在編譯器中表現(xiàn)為具體的數(shù)值)和變量名綁定,變量類型決定了這個地址的延續(xù)長度

搞清楚:變量、變量名、變量類型的三個概念的含義和區(qū)別

//左值和右值:賦值運(yùn)算符左邊的就是左值,右邊的就是右值,賦值就是把右值里面的東西給左值;所以右值里面必須有東西(如常量,變量),左值必須能接收東西(如變量)

20、指針和數(shù)組的天生關(guān)系

數(shù)組就是內(nèi)存地址連續(xù)的、類型相同(也就是大小相同)的一連串元素(變量)。這就決定了數(shù)組天生就適合使用指針進(jìn)行訪問,數(shù)組訪問有兩種,一種是通過數(shù)組下標(biāo)進(jìn)行訪問(也就是 a[0];);

一種是通過指針進(jìn)行訪問(也就是 *(a+2);)。

編譯器實(shí)質(zhì)都是通過指針訪問數(shù)組,數(shù)組下標(biāo)訪問是C語言提供給編程者的一種方便方法。

定義一個數(shù)組  int a[6];

a 表示數(shù)組首元素首地址,類型是int *類型,意義和數(shù)值等同于&a[0],兩者可以相互替換。

&a 表示整個數(shù)組的首地址,類型是數(shù)組指針。

指針變量 +1,表示指向數(shù)組的下一個元素,而不是真的數(shù)值+1;也就是加1*sizeof(數(shù)據(jù)類型);

在32位系統(tǒng)中,所有的指針變量所占的內(nèi)存空間都是4字節(jié)

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價比高”等特點(diǎn)與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。

文章名稱:C語言內(nèi)存這個話題-創(chuàng)新互聯(lián)
網(wǎng)站鏈接:http://muchs.cn/article14/eiede.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供搜索引擎優(yōu)化、網(wǎng)站導(dǎo)航、建站公司全網(wǎng)營銷推廣、網(wǎng)站改版動態(tài)網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都網(wǎng)站建設(shè)