www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁 > 芯聞號 > 充電吧
[導(dǎo)讀]C語言高級部分??一、內(nèi)存大話題1.0、內(nèi)存就是程序的立足之地,體現(xiàn)內(nèi)存重要性。1.1、內(nèi)存理解:內(nèi)存物理看是有很多個Bank(就是行列陣式的存儲芯片),每一個Bank的列就是位寬 ,每一行就是Wor

C語言高級部分?
?
一、內(nèi)存大話題
1.0、內(nèi)存就是程序的立足之地,體現(xiàn)內(nèi)存重要性。
1.1、內(nèi)存理解:內(nèi)存物理看是有很多個Bank(就是行列陣式的存儲芯片),每一個Bank的列就是位寬 ,每一行就是Words,則存儲單元數(shù)量=行數(shù)(words)×列數(shù)(位寬)×Bank的數(shù)量;通常也用M×W的方式來表示芯片的容量(或者說是芯片的規(guī)格/組織結(jié)構(gòu))。
? ? ? ? ? M是以位寬為單位的總?cè)萘浚瑔挝皇钦?,W代表位寬, 單位是bit。計算出來的芯片容量也是以bit為單位,但用戶可以采用除以8的方法換算為字節(jié)(Byte)。比如8M×8,這是一個8bit位寬芯片,有8M個存儲單元,總?cè)萘渴?4Mbit(8MB)。?
1.2、c語言中其實沒有bool類型:以0表示假,非0表示真,則在內(nèi)存存儲是以int型存放的。如果想要表示真假,可以用int/char型做替換,在c++中就有bool x=true/false;? ?
1.3、內(nèi)存對齊:內(nèi)存對齊(提高訪問效率速度,編譯器一般默認(rèn)是4字節(jié)對齊)
1.4、char/int/short/long/float/double型:放在內(nèi)存的長度和解析作用。(int *)0,使0地址指向一個int型。又比如0000111010101可以解析成int型也可以解析成float型。? ?

1.5、Linux內(nèi)核是面向?qū)ο蟮?,而c語言是面向過程的,但可以用結(jié)構(gòu)體內(nèi)嵌指針變成面向?qū)ο?。?

struct student

{

int age; ? ?//變量
int lenth; ? //將相當(dāng)于一個類,有變量有函數(shù)
char *name;
void (*eat)(void); ?//函數(shù)指針

?}

1.6、棧的理解:

(1) 運行時自動分配&自動回收:棧是自動管理的,程序員不需要手工干預(yù)。方便簡單。(表現(xiàn)在匯編代碼,編譯時,會自動編譯成匯編碼實現(xiàn)函數(shù)調(diào)用完立即改變棧頂)

(2) 反復(fù)使用:棧內(nèi)存在程序中其實就是那一塊空間,程序反復(fù)使用這一塊空間。(硬件上有個寄存器,用來存放棧的棧頂?shù)刂罚瑮J怯写笮〉目臻g)
(3) 臟內(nèi)存:棧內(nèi)存由于反復(fù)使用,每次使用后程序不會去清理,因此分配到時保留原來的值。
(4) 臨時性:(函數(shù)不能返回棧變量的指針,因為這個空間是臨時的)
(5) 棧會溢出:因為操作系統(tǒng)事先給定了棧的大小,如果在函數(shù)中無窮盡的分配棧內(nèi)存總能用完。棧的操作(怎么出棧怎么入棧)是由具體硬件來干預(yù),程序員只要明白原理就可以了, 但是要給相應(yīng)的棧寄存器賦值。當(dāng)調(diào)用函數(shù)時,變量會自動放在棧中(入棧)當(dāng)函數(shù)調(diào)用完后,棧會自動出棧.
? ( 6 ) ?棧的 "發(fā)展"有四種情況,滿增棧,滿減棧,空增棧,空減棧,至于是那種要根據(jù)編譯器決定,而s5pv210 是滿減棧。

1.7、堆的理解:

(1)操作系統(tǒng)堆管理器管理:堆管理器是操作系統(tǒng)的一個模塊,堆管理內(nèi)存分配靈活,按需分配。

(2)大塊內(nèi)存:堆內(nèi)存管理者總量很大的操作系統(tǒng)內(nèi)存塊,各進(jìn)程可以按需申請使用,使用完釋放。 ? ??
(3)臟內(nèi)存:堆內(nèi)存也是反復(fù)使用的,而且使用者用完釋放前不會清除,因此也是臟的。
(4)臨時性:堆內(nèi)存只在malloc和free之間屬于我這個進(jìn)程,而可以訪問。在malloc之前和free之后都不能再訪問,否則會有不可預(yù)料的后果。
(5)程序手動申請&釋放:手工意思是需要寫代碼去申請malloc和釋放free。(記?。翰灰焉暾埖牡刂方o搞丟了, 不然自己用不了,也釋放不了)
? ? ? ? ? 申請一段內(nèi)存,可以是: malloc(10*sizeof ( int ) ); 原型:void *malloc(size_t size); ?//指針函數(shù) size_t是宏定義int 都是便于可移植性 ,返回一個內(nèi)存地址,void *可以看出,希望申請的內(nèi)存用來存放什么就強制類型什么。? ? ?calloc( 10,sizeof ( int ) ); 原型:void *calloc(size_t nmemb, size_t size);// nmemb個單元,每個單元size字節(jié)
? ? ? ? ? ? void *realloc(void *ptr, size_t size);// 改變原來申請的空間的大小的ptr是原來申請內(nèi)存的指針,size是想要重新申請內(nèi)存的大小
使用就是*(p+1)=12 ? ; ? ?*(P+3)=110;
? ? ? 申請失敗返回NULL,申請成功返回一個地址,申請之后一定要檢驗(NULL!=p)用完一定要 ? free ( p ) ?;釋放后不是不能用,是不應(yīng)該使用了??梢越o它“洗盤子‘,p=NULL;? 其實申請的內(nèi)存并不能真正改變大小,原理是先重新申請一段內(nèi)存,然后把原來申請的內(nèi)存上的內(nèi)容復(fù)制到新的內(nèi)存上,然后釋放掉原來的內(nèi)存,返回新的指針。
? ?(6) 在申請內(nèi)存時,malloc(0)其實也是成功的,因為系統(tǒng)規(guī)定少于一定數(shù)目的大小,都申請規(guī)定的大小,如在win32系統(tǒng)下申請少于32字節(jié)的地址,最后申請到的空間是32字節(jié)。

1.8、內(nèi)存里的數(shù)據(jù):?

(1)代碼段:存放代碼二進(jìn)制、常量(char *p="linux",則”linux“存放在代碼段,是不可更改的)

(2) 數(shù)據(jù)段: ?存放非0全局變量、靜態(tài)局部變量(局部只屬于函數(shù)的,不是整個程序的)
(3) bss ? ? : ?存放為0的全局變量/為0的靜態(tài)局部變量、存放未初始化全局變量/靜態(tài)局部變量
? 注意:const int a=9; 有兩種存放方式:第一種確實存放在代碼段,讓a不能修改,第二種是仍然存放在數(shù)據(jù)段中,讓編譯器來判斷,如果有改變的代碼就會報錯。 至于那種,是不確定的,像單片機就屬于第一種。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
1.9、《1》一個源文件實際上是以段為單位編譯成連接成可執(zhí)行文件(a .out );這個可執(zhí)行文件總的說是分為數(shù)據(jù)段,代碼段,自定義段,數(shù)據(jù)段還可以細(xì)分成 .bbs 段。而雜段會在執(zhí)行的時候拿掉。所以a.out分為雜段,數(shù)據(jù)段(存放的是非0全局變量).bbs段,代碼段。
《2》內(nèi)存實際上被劃分了兩大區(qū)域,一個是系統(tǒng)區(qū)域,另一個是用戶區(qū)域,而每一個區(qū)域又被劃分成了幾個小區(qū)域,有堆,棧,代碼區(qū),.bbs區(qū),數(shù)據(jù)區(qū)(存放的是非0全局變量)。
? ? ? ? ?《3》對于有操作系統(tǒng)而言, ?當(dāng)我們在執(zhí)行a.out可執(zhí)行文件時,執(zhí)行這個文件的那套程序會幫我們把雜段清掉,然后把相應(yīng)的段加載到內(nèi)存對應(yīng)的段。對于裸機程序而言,我們是使用一套工具將a.elf的可執(zhí)行程序給清掉了所有段的符號信息,把?純凈的二進(jìn)制做成.bin格式的燒錄文件。所以我們加載到內(nèi)存的程序是連續(xù)的,也就是說代碼段和數(shù)據(jù)段、.bbs段都是連續(xù)的。當(dāng)然,棧空間是我們自己設(shè)置的。而且在裸機中我們不能使用malloc函數(shù),因為我們使用的只是編譯器、連接器工具沒有集成庫函數(shù),沒有定義堆空間區(qū)。
《4》大總結(jié)多程序運行情況: 在Linux系統(tǒng)中運行cdw1.out時,運行這個文件的那套程序會幫我們把相應(yīng)的段加載到內(nèi)存對應(yīng)的段。然后操作系統(tǒng)會把下載到內(nèi)存的具體物理地址與每條命令(32位)的鏈接地址映射到TTB中(一段內(nèi)存空間),當(dāng)我們又運行cdw2.out時,同樣也像cdw1.out一樣加載進(jìn)去,并映射到TTB表中。而且這兩個.out文件默認(rèn)都是鏈接0地址(邏輯),當(dāng)cpu發(fā)出一個虛擬地址(Linux中程序邏輯地址)通過TTB查找的物理地址是不一樣的。所以對于每一個程序而言,它獨占4G的內(nèi)存空間,看不到其他程序。

二、位操作
2.1 ?~(0u)是全1;
2.2 位與& ? ? 位或 | ? ? ? ? ? ?位取反~ ? ? ? 位異或^
2.3、位與、位或、位異或的特點總結(jié):
? ? ? ? ?位與:(任何數(shù),其實就是1或者0)與1位與無變化,與0位與變成0
? ? ? ? ?位或:(任何數(shù),其實就是1或者0)與1位或變成1,與0位或無變化
? ? ? ? ?位異或:(任何數(shù),其實就是1或者0)與1位異或會取反,與0位異或無變化
?
2.4、左移位<< 與右移位>> ?C語言的移位要取決于數(shù)據(jù)類型。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 對于無符號數(shù),左移時右側(cè)補0(相當(dāng)于邏輯移位)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 對于無符號數(shù),右移時左側(cè)補0(相當(dāng)于邏輯移位)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 對于有符號數(shù),左移時右側(cè)補0(叫算術(shù)移位,相當(dāng)于邏輯移位)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 對于有符號數(shù),右移時左側(cè)補符號位(如果正數(shù)就補0,負(fù)數(shù)就補1,叫算術(shù)移位)
?
2.5、小記:常與 ?1 拿來 做位運算。讓他取反、移位 得到想要的數(shù)。

2.6、直接用宏來置位、復(fù)位(最右邊為第1位)。 置位置1,復(fù)位置0 ?;
? ? ? ? ? #define SET_NTH_BIT(x, n) ?(x | ((1U)<<(n-1)))
? ? ? ? ? #define CLEAR_NTH_BIT(x, n) (x & ~((1U)<<(n-1)))

三、指針—精髓?
3.1 ?printf("%p n"); 其中%p表示輸出一個指針,就是指針變量(其存放的那個地址),可以理解為輸出一個地址。

3.2 ?int* p1, p2 ; ? ? 等同于 int *p1; ? int ?p2;  int?。穑剑ⅲ蹋椋睿酰?,其不能改變*P,因為”linux"是一個常數(shù)。

3.3 ( 代碼規(guī)范性 )在定義指針時,同時賦值為NULL,在用指針時,先判斷它是不是NULL。尤其是在malloc申請內(nèi)存后,free(p);則一定要讓p=NULL

3.4 ?C/C++中對NULL的理解: #ifdef _cplusplus// 定義這個符號就表示當(dāng)前是C++環(huán)境
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#define NULL 0;// 在C++中NULL就是0
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#else
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#define NULL (void *) 0;// 在C中NULL是強制類型轉(zhuǎn)換為void *的0
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#endif
3.5、修飾詞:const (修飾變量為常量,應(yīng)該理解為不應(yīng)該去變它,當(dāng)作常量,而并非永遠(yuǎn)不能改變,當(dāng)然要看具體運行環(huán)境,在gcc,const 這種就可以采用指針方式修改,但是
在VC6.6++中就不可以修改):其雖然是當(dāng)作常數(shù),但是仍然存放在數(shù)據(jù)段中,用指針仍然可以改變值。
第一種:const int *p; ??
第二種:int const *p;
第三種:int * const p;
第四種:const int * const p;
3.6、 數(shù)組 int a[2]; 其中a是指首元素的首地址,&a是整個數(shù)組的收地址(數(shù)組指針,其這個指針指向一個數(shù)組),他們的值是一樣的,但意義不一樣,可以參照 int a; int *p=&a; 來理解。數(shù)組和指針天生姻緣在于數(shù)組名;int a[3]; int* p=a;是可以的,但是 int *p=&a;就會報錯,盡管他們的值是一樣的,但意義不一樣,所以是不允許的,除非強制類型轉(zhuǎn)換。在訪問時是a[0],其實編譯器會把它變成*(a+0)的方式,只是用a[0]看起來更方便,封裝了一下而已,實質(zhì)還是指針。

3.7、 siziof()是一個運算符,測試所占內(nèi)存空間,如 int a[100] ;sizeof(a)=400;?與strlen( )要有所區(qū)別,他是測字符串實際長度的,不包括‘