C語言程式設計知識總結
po主非科班,要學習資料結構 演算法,發現mooc上都是用c教,重新認真學了遍c,給自己總結一下。。
int main (void)
``
關鍵字void表示 mian () 函式不需要引數。 `
return 0;
它結束main()函式的執行,並向系統返回了一個整數0,作為程式的結束狀態。由於main()函式的返回值是整型數,因此,任何整數都可以作為返回值。 按照慣例,如果main()函式返回0,說明程式執行正常,返回其他數字則用於表示各種不同的錯誤情況。
flaot 和 double 都是浮點型, 用於存放浮點數(實數), 區別在於double型資料佔用空間更大,精度更高,取值範圍更大。float 型資料用 %f,而double 型資料使用%lf。 l是long的首字母。
常用數學函式
- 平方根函式
sqrt (x)
- 絕對值函式
fabs (x)
- 冪函式
pow (x)
迴圈語句只能是一條語句。這是初學者常犯的錯誤,而且在程式執行時系統沒有任何錯誤提示。
如何迴圈語句由多條語句組成,必須由大括號把他們括起來,變成一條複合語句。
return 語句只能返回一個值
一般情況下把全域性變數定義在程式的最前面,即第一個函式的前面。
由於全域性變數和區域性變數作用範圍不同,允許他們同名。當某函式的區域性變數與全域性變數同名時,在該函式中全域性變數不起作用,而由區域性變數起作用。
變數從定義開始分配儲存單元,到執行結束儲存單元被回收,整個過程稱為變數生存週期。當main()函式呼叫其他函式時,由於main()還未執行結束,其區域性變數仍然存在,還在生存週期中。全域性變數的生存週期為整個程式執行週期。
C語言把儲存所有變數的資料區分成動態儲存區和靜態儲存區。
動態儲存區是使用堆疊來管理的,適合函式動態分配與回收儲存單元。
靜態儲存區相對固定,管理比較簡單,它用於存放全域性變數和靜態變數。
靜態儲存區中,除了全域性變數以外,還有靜態區域性變數,由於儲存單元被保留,一旦含有靜態區域性變數的函式再次被呼叫,則靜態區域性變數會被重新啟用,上一次函式呼叫後的值仍然被儲存,可以供本次呼叫後繼續使用。
靜態變數定義格式:
static 型別名 變量表
自動變數如果沒有賦初值,其儲存單位中將是隨機值,就靜態變數而言,如果定義時沒有初始值,系統將自動賦0。並且賦初值只在函式第一次呼叫時起作用,以後呼叫都按前一次呼叫保留的值使用。這是因為靜態區域性變數的生存週期始於函式的第一次呼叫,貫穿整個程式。當函式第一次呼叫時,靜態區域性變數的記憶體單元得以分配,賦以初值,而函式被再次呼叫時,此靜態區域性變數單元已經存在,計算機不會再次為它分配單元,賦初值也不會再發生。
但靜態區域性變數受變數作用範圍限制,不能作用於其他函式(包括主函式)。
靜態區域性變數和全域性變數一樣,位於靜態儲存區,他們的共同點是生存週期貫穿整個程式執行過程。區別在於作用範圍不同,全域性變數可作用於所有函式,靜態變數只能用於定義函式,而不能用於其他函式。
字元型變數記憶體佔用一個位元組,字元型常量指單個字元,用一對單引號來表示。
ch -‘a’ + ‘A’ 可把小寫字母轉換為大寫字母。
陣列名是一個地址常量,存放陣列記憶體空間的首地址。
矩陣術語與二維陣列下標的對應關係
- 主對角線 從矩陣的左上角至右下角的連線 i == j
- 上三角 主對角線以上的部分 i <= j
- 下三角 主對角線以下的部分 i >= j
- 副對角線 從矩陣的右上角至左下角的連線 i + j == N-1
字串可以存放在一維字串中。例如
static char s[6] = {'H', 'a', 'a', 'p', 'y', '\0'}
陣列s中就存放了字串’Happy’了。
字元陣列的初始化還可以使用字串常量,上述初始化等價於:
static char s [6] = {"Happy"};
或者
static char s[6] = "Happy";
字串由有效字元和字串結束符’\0’組成。
區分”a”和‘a’,前者是字串常量,包括’a’和’\0’兩個字元,用一位字元陣列存放;後者是字元常量,只有一個字元,可以賦給字元變數。
將十六進位制字元轉換為十進位制數number的表示式如下:
number = number * 16 + hexad[i] - ‘0’
number = number * 16 + hexad[i] - ‘A’ + 10
number = number * 16 + hexad[i] - ‘a’ + 10
指標
int型變數佔2個位元組
char型變數佔1個位元組
float型和double型分別需要佔用4和8個位元組的記憶體單元
如果未加說明,把指標和指標變數同等對待,都是指存放記憶體地址的指標變數。
在定義指標變數時需要使用指標宣告符 *, 但指標宣告符並不是指標的組成部分。例如,定義 int *p; 說明p是指標變數,而不是 *p。
在程式中,“*”除了被用於定義指標變數外,還被用於訪問指標所指向的變數,它也稱為間接運算子。
在C語言中實參和形參之間的資料傳遞是單向的“值傳遞”方式,呼叫函式不能改變實參變數的值,當指標變數作為函式時也遵守這一個規則。呼叫函式不能改變實參指標變數的值,但可以改變實參指標變數所指向的變數的值。這樣的機制被稱為引用呼叫。
氣泡排序
void bubble (int a[], int n)
{
int i, j, t;
for (i = 1; i < n; i++)
for (j = 0; j < n-i; j++)
if (a[j] > a[j+1]) {
t = a[j]; a[j] = a[j+1]; a[j+1] = t;
}
}
選擇排序和氣泡排序初始條件:
選擇排序
i = 0; i < n-1
index = i; //index 存放最小值的下標
j = i+1; j < n
if (a[j] < a[index]) index = j;
氣泡排序
i = 1; i < n;
j = 0; j < n-i;
if (a[j] > a[j+1])
int a[] 等價於 int *a
字元陣列與字元指標都可以處理字串,但兩者之間有重要區別。例如
char sa[] = "This is a string";
char *sp = "This is a string";
字元陣列sa在記憶體中佔用一塊連續的單元,有確定的地址,每個陣列元素放字串的一個字元,字串就存放在陣列中。字元指標sp只佔用一個可以存放地址的記憶體單元,儲存字元首字元的地址,而不是將字串放到字串指標變數中去。
採用函式gets()輸入的字串允許帶空格。如果輸入成功則返回值是字串第一個字元的地址,如果輸入失敗則返回NULL。
puts()輸出遇’\0’自動將其轉換為’\n’,即輸出字串後換行。同樣函式puts()也有返回值,如果成功執行了輸出字串的操作,則返回換行符號’\n’,否則返回EOF。
函式printf()和函式puts()的區別在於後者輸出字串會自動換行。
函式scanf()只能輸入不帶空格的字串,而gets()則沒有這個限制。
strcpy (s1, s2);
字串複製函式
引數s1必須是字元型陣列基地址,引數s2可以是字元型陣列名或字串常量。
字串連線函式strcat (s1, s2)
引數s1必須是字元型陣列基地址,引數s2可以是字元型陣列名或字串常量。
字串比較函式strcmp (s1, s2);
若s1和s2相等,返回0。
若s1大於s2,返回一個正數。
若s1小於s2,則返回一個負數。
字串長度函式 strlen(s1)
計算字串的有效個數
- exit(0):正常執行程式並退出程式;
- exit(1):非正常執行導致退出程式;
- return():返回函式,若在主函式中,則會退出函式並返回一值。
**
- malloc () 呼叫malloc()時, 應該使用sizeof計算儲存塊大小,不要直接寫數值。若申請成功,則返回一個指向被分配記憶體空間的起始地址的指標;若申請記憶體空間不成功,則返回NULL(0)。
- calloc () 在記憶體的動態儲存區中分配n個連續空間,每一個儲存空間的長度為size,並且分配後還把儲存塊裡的全部初始化為0.若申請成功,則返回一個指向被分配記憶體空間的起始地址的指標;若申請記憶體空間不成功,則返回NULL(0)。
- malloc() 對所分配的儲存塊不做任何事情,calloc()對整個區域進行初始化。
- free() 為了保證動態儲存塊的有效利用,在知道某個動態分配的儲存塊不再用用時,就應該及時把他釋放。
- realloc() 更改以前的儲存分配。
**free()詳解 記憶體釋放
既然有分配,那就必須有釋放。不然的話,有限的記憶體總會用光,而沒有釋放的記憶體卻在空閒。與malloc對應的就是free函數了。free函式只有一個引數,就是所要釋放的記憶體塊的首地址。比如上例:free(p);
free函式看上去挺狠的,但它到底作了什麼呢?
其實它就做了一件事:斬斷指標變數與這塊記憶體的關係。
比如上面的例子,我們可以說malloc函式分配的記憶體塊是屬於p的,因為我們對這塊記憶體的訪問都需要通過p來進行。free函式就是把這塊記憶體和p之間的所有關係斬斷。從此p和那塊記憶體之間再無瓜葛。至於指標變數p本身儲存的地址並沒有改變,但是它對這個地址處的那塊記憶體卻已經沒有所有權了。那塊被釋放的記憶體裡面儲存的值也沒有改變,只是再也沒有辦法使用了。
這就是free函式的功能。按照上面的分析,如果對p連續兩次以上使用free函式,肯定會發生錯誤。因為第一使用free函式時,p所屬的記憶體已經被釋放,第二次使用時已經無記憶體可釋放了。關於這點,我(陳正衝老師)上課時讓學生記住的是:一定要一夫一妻制,不然肯定出錯。
malloc兩次只free一次會記憶體洩漏;malloc一次free兩次肯定會出錯。也就是說,在程式中malloc的使用次數一定要和free相等,否則必有錯誤。這種錯誤主要發生在迴圈使用malloc函式時,往往把malloc和free次數弄錯了。
4、記憶體釋放之後
既然使用free函式之後指標變數p本身儲存的地址並沒有改變,那我們就需要重新把p的值變為NULL:p = NULL;
這個NULL就是我們前面所說的”栓野狗的鏈子”。如果你不栓起來遲早會出問題的**
**
指標函式是指函式的返回值是地址, *不帶括號
函式指標是指定義一個指標變數,接受函式的入口地址,這就是指向函式的指標,也稱為函式指標。
結構也是一種構造資料型別(或叫派生資料型別)
當p指向結構變數s1時,下面三條語句的效果是一樣的:
s1.num = 101;
(*p).num = 101;
p->num = 101;
一般按照結構化程式設計方法組織函式,主要原則可以概括為“自頂向下, 逐步求精, 函式實現”。
遞迴程式設計
- 遞迴出口:即遞迴的結束條件,到何時不再遞迴呼叫下去。
- 遞迴式子:遞迴的表示式,如fact (n) = n * fact (n-1)。
巨集定義#define是C語言中常用的功能。用巨集來定義一些符號常量,可以方便程式的編制。
巨集定義的格式:
#define 巨集名 巨集定義字串
巨集引用形式與函式呼叫非常相似,但兩者的實現完全不同。巨集替換在程式編譯處理時完成。
C語言的編譯預處理主要包括檔案包含(#include)、巨集定義(#define)和條件編譯。
extern 變數名錶
他只起說明作用,不分配儲存單元,對應的儲存單元在全域性變數定義時分配。
C語言的靜態全域性變數可以把變數的作用範圍僅侷限於當前的檔案模組中,即使其他檔案模組使用外部變數宣告,也不能使用該變數。