1、內存管理: 靜態分配和動態分配 動態分配:程序執行的時候根據需要動態分配。 靜態分配:編譯的時候分配。程序執行之前進行的。 內存的幾個區: 代碼段、數據段、BSS、棧、堆 靜態分配和動態分配的區別: 靜態對象是有名字的變量,我們直接對其進行操作. 而動態對象是沒有名字的變量,我們通過指針間接地對它進行操 作。 靜態對象的分配與釋放由編譯器自動處理.動態對象的分配與釋放, 必須由程序員顯式地管理, 相對來說比較容易出 錯。 2、動態內存分配: 申請一個動態內存空間 1、malloc函數 malloc(長度以字節為單位) int *p =(int *)malloc(50); 注意:申請0字節內存,函數並不返回NULL,而是返回一個正常的內存地址。 2、calloc函數 calloc(n[申請多少個],size長度為多少字節); int p[10];申請長度為10的整型 int *p=(int *)calloc(10,sizeof(int)); 3、realloc(指針,長度至多少) 將2定義的內存空間改至100; p=realloc(p,100); 4、申請後,還可以釋放,使用free()函數實現。 free(動態空間的指針); 斬斷指針變量和這塊內存的關系。從此p和那塊內存之間再無瓜葛。空間能夠重新被利用。 3、內存洩露 一塊動態分配的內存,我們不在擁有指向這塊內存的指針,因此我們沒有辦法將它返回給程序供以後重新使用。 引起內存洩露的可能性: 1)重新賦值 int *p = (int *)malloc(40); int *q = (int *)malloc(40); p=q; P原來指向的空間再也無法還給系統,所以造成洩露。 解決方案: int *temp; int *p = (int *)malloc(40); temp=p;//把p的地址存放在臨時變量temp中 int *q = (int *)malloc(40); p=q; 再想使用原來的p內存空間,就可以p=temp; 2)先釋放父級 假設上述兩個區域都是動態申請和分配(p和q),需要手工的釋放。 如果free(p)將會造成內存洩露. 原因是:p所指向的內存中有區域新申請了新的子內存空間 如果p被釋放,那麼p內存區域中指向的子內存空間無法釋放。 解決: 先釋放子內存空間 free(q); 再釋放父級空間 free(p); 3)返回值(新申請的動態內存地址)的不正確處理 int* apply(){ return (int*)malloc(20); //返回的是新申請的內存空間的首地址 } apply(); //進行調用 apply()函數的返回值,沒有給任何指針 4、野指針: 指向“垃圾”內存的指針。 1)未被初始化的指針 解決:讓指針=0或者=NULL; 2)free之後沒有被賦值NULL 解決:讓指針=0或者=NULL; 3)指針訪問越界 解決:控制不讓越界 C語言中文件操作 概念:存儲在外部介質上的數據的集合 簡單分類: -程序的源文件 .c .obj .exe -程序數據文件 從外部獲取的一批數據 C語言對文件操作有如下步驟: (1)、導入庫函數 stdio.h (2)、定義文件的指針 FILE ----(特殊的結構體,不許進行聲明) (3)、打開文件 fopen([路徑]文件名,打開方式) 路徑 --> ./ ../ D:\\temp\a.txt 打開方式: r 只讀 w 只寫 a 追加 r+ 讀寫 w+ 讀寫 a+ 追加 t 打開文本文件 b 打開二進制文件 (音頻、視頻、圖像) (4)、文件讀寫操作 (5)、關閉文件指針 fclose(文件指針); 5、輸入輸出流 輸入操作時,數據從文件流向計算機內存。 輸出操作時,數據從計算機流向文件。 6、文件標識符: (1)文件路徑。 (2)文件名主干 。(3)文件後綴。 7、文件緩沖區 概念:緩沖文件系統是指系統自動的在內存區為程序中每個正在使用的文件開辟一個文件緩沖區。 8、讀寫字符的函數: fgetc(fpr); 從文件中讀取字符。 fputc(ch,fpw); 把ch寫入到fpw指向的文件中。 fgets(str,n,fp);從fp指向的文件讀入長度為(n-1)的字符串,存放到字符數組str中。 fputs(str,fp);str所指向的字符串寫到文件指針變量fp所指向的文件中。 fprintf(文件指針,格式字符串,輸出表列); fscanf (文件指針,格式字符串,輸入表列); fread(地址,要讀寫的字節數,要讀寫多少個數據項,FILE類型指針); fwrite(地址,要讀寫的字節數,要讀寫多少個數據項,FILE類型指針); 注意:完成一次寫操(fwrite())作後必須關閉流(fclose()); 完成一次讀操作(fread())後,如果沒有關閉流(fclose()),則指針(FILE * fp)自動向後移動前一次讀寫的長度,不關 閉流繼續下一次讀操作則接著上次的輸出繼續輸出。 9、預編譯處理 概念:是指在進行編譯的第一遍掃描(詞法掃描和語法分析)之前所做的工作。 10、預編譯處理命令 宏命令(Macro) 文件包含命令(include) 條件編譯命令 這些命令均以#開頭,以區別於語句。 11、宏定義的分類 1)不帶參數的宏:#define 標識符 字符串 e.g :#define PI 3.1415926 #define:宏定義命令。 #undef:終止宏定義命令。 注意:宏定義不是C語句,後面不能有分號。如果加入分號,則連分號一起替換。用雙引號括起來的字符串,即使與宏 名相同,也不替換 2)帶參數的宏 #define 宏名 (參數表) 字符串 12、帶參宏和函數的區別 1)處理時間:帶參宏是編譯時。函數是程序運行時。 2)參數類型:帶參宏是無類型問題。函數是定義參數、形參類型 3)處理過程:帶參宏是不分配內存,簡單的字符置換。函數是分配內存,先求實參值,再代入形參。 4)程序長度:帶參宏是變長。函數是不變。 5)運行速度:帶參宏是不占運行時間。函數是調用和返回占時間。 13、條件編譯 1.條件編譯的語句形式: #ifdef 標識符 程序段1 #else 程序段2 #endif 其作用是:如果“標識符”已定義,則編譯“程序段1”,否則編譯“程序段2” 。 #if 表達式 程序段1 #else 程序段2 #endif 其作用是:當“表達式”值為非0 ,則編譯“程序段1“,否則編譯“程序段2”。