c語言重點整理
1. sizeof與strlen的區別與聯絡
a)sizeof
sizeof(...)是運算子,在標頭檔案中typedef為unsigned int,其值在編譯時即計算好了,引數可以是陣列、指標、型別、物件、函式等。
它的功能是:獲得保證能容納實現所建立的最大物件的位元組大小。
由於在編譯時計算,因此sizeof不能用來返回動態分配的記憶體空間的大小。實際上,用sizeof來返回型別以及靜態分配的物件、結構或陣列所佔的空間,返回值跟物件、結構、陣列所儲存的內容沒有關係。
具體而言,當引數分別如下時,sizeof返回的值表示的含義如下:
陣列——編譯時分配的陣列空間大小;
指標——儲存該指標所用的空間大小(儲存該指標的位址的長度,是長整型,應該為4);
型別——該型別所佔的空間大小;
物件——物件的實際占用空間大小;
函式——函式的返回型別所佔的空間大小。函式的返回型別不能是void。
b)strlen
strlen(...)是函式,要在執行時才能計算。引數必須是字元型指標(char*)。當陣列名作為引數傳入時,實際上陣列就退化成指標了。
它的功能是:返回字串的長度。該字串可能是自己定義的,也可能是記憶體中隨機的,該函式實際完成的功能是從代表該字串的第乙個位址開始遍歷,直到遇到結束符null。返回的長度大小不包括null。
c)舉例:
eg1、char arr[10] = "what?";
int len_one = strlen(arr);
int len_two = sizeof(arr);
cout << len_one << " and " << len_two << endl;
輸出結果為:5 and 10
sizeof返回定義arr陣列時,編譯器為其分配的陣列空間大小,不關心裡面存了多少資料。strlen只關心儲存的資料內容,不關心空間的大小和型別。
eg2、char * parr = new char[10];
int len_one = strlen(parr);
int len_two = sizeof(parr);
int len_three = sizeof(*parr);
cout << len_one << " and " << len_two << " and " << len_three << endl;
輸出結果:23 and 4 and 1
第乙個輸出結果23實際上每次執行可能不一樣,這取決於parr裡面存了什麼(從parr[0]開始知道遇到第乙個null結束);第二個結果實際上本意是想計算parr所指向的動態記憶體空間的大小,但是事與願違,sizeof認為parr是個字元指標,因此返回的是該指標所佔的空間(指標的儲存用的是長整型,所以為4);第三個結果,由於*parr所代表的是parr所指的位址空間存放的字元,所以長度為1。
①sizeof操作符的結果型別是size_t,它在標頭檔案中typedef為unsigned int型別。
該型別保證能容納實現所建立的最大物件的位元組大小。
②sizeof是算符,strlen是函式。
③sizeof可以用型別做引數,strlen只能用char*做引數,且必須是以''\0''結尾的。
sizeof還可以用函式做引數,比如:
short f();
printf("%d\n", sizeof(f()));
輸出的結果是sizeof(short),即2。
④陣列做sizeof的引數不退化,傳遞給strlen就退化為指標了。
⑤大部分編譯程式 在編譯的時候就把sizeof計算過了 是型別或是變數的長度這就是sizeof(x)可以用來定義陣列維數的原因
char str[20]="0123456789";
int a=strlen(str); //a=10;
int b=sizeof(str); //而b=20;
⑥strlen的結果要在執行的時候才能計算出來,時用來計算字串的長度,不是型別佔記憶體的大小。
⑦.sizeof後如果是型別必須加括弧,如果是變數名可以不加括弧。這是因為sizeof是個操作符不是個函式。
⑧當適用了於乙個結構型別時或變數, sizeof 返回實際的大小,
當適用一靜態地空間陣列, sizeof 歸還全部陣列的尺寸。
sizeof 操作符不能返回動態地被分派了的陣列或外部的陣列的尺寸
陣列作為引數傳給函式時傳的是指標而不是陣列,傳遞的是陣列的首位址,
如: fun(char [8])
fun(char )
都等價於 fun(char *)
在c++裡引數傳遞陣列永遠都是傳遞指向陣列首元素的指標,編譯器不知道陣列的大小
如果想在函式內知道陣列的大小, 需要這樣做:
進入函式後用memcpy拷貝出來,長度由另乙個形參傳進去
fun(unsiged char *p1, int len)
unsigned char* buf = new unsigned char[len+1]
memcpy(buf, p1, len);
char str[20]="0123456789";
int a=strlen(str); //a=10; >>>> strlen 計算字串的長度,以結束符 0x00 為字串結束。
int b=sizeof(str); //而b=20; >>>> sizeof 計算的則是分配的陣列 str[20] 所佔的記憶體空間的大小,不受裡面儲存的內容改變。
上面是對靜態陣列處理的結果,如果是對指標,結果就不一樣了
char* ss = "0123456789";
sizeof(ss) 結果 4 ===》ss是指向字串常量的字元指標,sizeof 獲得的是乙個指標的之所佔的空間,應該是
長整型的,所以是4
sizeof(*ss) 結果 1 ===》*ss是第乙個字元 其實就是獲得了字串的第一位'0' 所佔的記憶體空間,是char類
型的,佔了 1 位
strlen(ss)= 10 >>>> 如果要獲得這個字串的長度,則一定要使用 strlen
2.值傳遞和位址傳遞
值傳遞是單向的,實參傳入到被調函式中,被調函式執行完就釋放空間,引數是傳不回來的;
位址傳遞是雙向的,因為實參和形参指的都是同一塊記憶體空間,實參傳入到被調函式中,這個引數是可以影響到主函式的;
#include void swap(int *x,int *y) ------是位址傳遞, 定義兩個指標變數x, y;
printf("2:x=%d, y=%d\n",*x,*y);}
int main()
值傳遞:
#include void swap(int x,int y) ------是值傳遞, 定義兩個變數x, y;
printf("2:x=%d, y=%d\n",x, y);}
int main()
3.static 和extern
a)static常見的有三種出現的位置:
如:static1.c 中 static int num; 這個num只能是static1.c中使用;
如果static2 .c 中使用 ,是編譯不過去的;
③在函式的前面;
如果是 在函式的前面加上static ,表示我這個函式只能在本檔案中使用;
b)extern
可以修飾全域性變數;
①在本檔案中,如何全域性變數定義在後面,在前面使用的時候,要加extern宣告一下;
②如果要使用另外乙個檔案中的變數,可以進行extern宣告一下,表示這個變數外部檔案可以用;
4.靜態儲存 ,動態儲存
靜態資料區:從檔案開始就存在,一直到檔案執行結束才結束 ;存放 靜態區域性變數 ,全域性變數 ;
5.資料儲存區域
棧區 : 存放的 區域性變數,形參 ;
堆區 : 使用者 ,程式設計師申請的空間 ,malloc()申請 的;
資料區 :初始化 的 ,未初始化的 ;
bss未初始化的 : 未初始化的全域性變數 ,static變數 ;
data初始化的 資料區 : 初始化的全域性變數 ,static變數 ,還有常量;
text**段 :存放可執行的**
6. 堆和棧的區別
棧 : 存放區域性變數 ,函式形參等 ,由 編譯器來分配和釋放 ;
堆區 :由程式設計師來申請釋放 ;----很容易造成記憶體洩露 ,耗盡;malloc---free配對 。
C語言重點散知識整理(二)
1.逗號隔開 2.從左向右依次執行,但是以最後乙個表示式為主 eg int len 3 4,5 6 結果 len 11 1.extern 宣告外部變數 備註 這裡說的是 宣告 宣告乙個變數或者函式是外部變數 思考 為什麼要這麼做呢,如果引入這個變數或者函式所在檔案的標頭檔案就可以直接訪問它們,似乎 ...
C語言重點散知識整理(三)
左值 放在等號左邊的值,代表其表示的儲存空間 指標可以作為左值是因為它是乙個變數 右值 放在等號右邊的值,變數放在右邊代表其所代表的內容 資料比較基礎,這裡不詳細介紹,這裡只單獨拿出來強調陣列作為函式的引數時的變化 1.一維陣列作為函式傳遞的引數時,它會降級成為乙個指向一維陣列元素的指標 2.二維陣...
中級C語言重點
一 關於記憶體使用與釋放的問題 1.記憶體的使用要慎重,在申請之前需要注意,不要忘記嵌入標頭檔案 include。在使用堆空間時,如使用scanf函式輸入函式,不要忘記堆緩衝區的清除,否則程式容易產生死迴圈,即使用語句 fflush stdin 2.注意區別malloc 與calloc 的區別 ma...