C語言之指針
阿新 • • 發佈:2018-03-26
就是 for 答案 基本類型 %d alloc 動態分配 快速 style
從0開始的非負整數 範圍:4G 【0---4G-1】 分類: 1.基本類型指針【重點】 附註: * 的含義
1.乘法 2.定義指針變量 int *p;//定義一個名字叫p的變量,int *表示p只能存放 int變量地址 3.指針運算符 該運算符放在已經定義好的指針變量的前面 如果p是一個已經定義好的指針變量 則*p表示以p的內容為地址的變量 如何通過被調函數修改主調函數普通變量的值 1.實參必須為該普通變量的地址 2.形參必須為指針變量 3.在被調函數中通過 *形參名 = ····· 的方式就可以修改主調函數相關變量的值 2.指針和數組 指針和一維數組 一維數組名: 一維數組名是個指針常量 它存放的是數組第一個元素的地址 下標和指針的關系 如果p是個指針變量,則 p[i]永遠等價於 *(p+i) 確定一個一維數組需要幾個參數【如果一個函數要接受一個一維數組,需要哪些條件】數組第一個元素的地址和數組長度
傳統數組的缺點: 1.數組的長度必須事先指定,且只能是常整數,不能是變量 例子: int a[5]; //OK int len = 5;int a[len];//error 2.傳統形式定義的數組,該數組的內存程序員無法手動釋放 在一個函數運行期間,系統為該函數中的數組所分配的空間會一直存在,直到該函數運行完畢時,數組的空間才會被系統釋放 3.數組的長度不能在函數運行的過程中動態的擴充或縮小 數組的長度一旦定義,其長度就不能再更改 4.A函數定義的數組在A函數運行期間可以被其他函數使用,但A函數運行完畢之後,A函數中的數組無法再被其他函數使用 傳統方式定義的數組不能跨函數使用 為什麽需要動態分配內存 動態數組很好的解決了傳統數組的這4個缺點 傳統數組也叫靜態數組 動態內存分配舉例--動態數組的構造
指針
指針和指針變量的關系 指針就是地址,地址就是指針 地址就是內存單元的編號 指針變量是存放地址(內存單元的編號)的變量 指針和指針變量是兩個不同的概念 但要註意:通常我們會把指針變量簡稱為指針表,實際含義不一樣 指針的本質就是一個操作受限的非負整數 重要性: 表示一些復雜的數據結構 快速的傳遞數據 減少了內存的耗用【重點】 使函數返回一個以上的值【重點】 能直接訪問硬件 能夠方便的處理字符串 是理解面向對象語言中引用的基礎 定義: 地址: 內存單元的編號從0開始的非負整數 範圍:4G 【0---4G-1】 分類: 1.基本類型指針【重點】 附註: *
1.乘法 2.定義指針變量 int *p;//定義一個名字叫p的變量,int *表示p只能存放 int變量地址 3.指針運算符 該運算符放在已經定義好的指針變量的前面 如果p是一個已經定義好的指針變量 則*p表示以p的內容為地址的變量 如何通過被調函數修改主調函數普通變量的值 1.實參必須為該普通變量的地址 2.形參必須為指針變量 3.在被調函數中通過 *形參名 = ····· 的方式就可以修改主調函數相關變量的值 2.指針和數組 指針和一維數組 一維數組名: 一維數組名是個指針常量 它存放的是數組第一個元素的地址 下標和指針的關系 如果p是個指針變量,則 p[i]永遠等價於 *(p+i) 確定一個一維數組需要幾個參數【如果一個函數要接受一個一維數組,需要哪些條件】數組第一個元素的地址和數組長度
# include <stdio.h> //f函數可以輸出任何一個一維數組的內容 void f(int * pArr,int len) { int i; for(i = 0;i < len;++i) printf("%d",*(pArr + i)); /*(pArr + i)等價於 pArr[i] 也等價於 數組[i] printf("\n"); } int main(void) { int a[5] = {1,2,3,4,5}; int b[6] = {-1,-2,-3,4,5,-6}; int c[100] = {1,99,22,33}; f(a,5); //a是int *類型,需要數組第一個元素的地址和長度 f(b,6); f(c,100); return 0; }
# include <stdio.h> //f函數可以輸出任何一個一維數組的內容 void f(int * pArr,int len) { pArr[3] = 88; } int main(void) { int a[6] = {1,2,3,4,5,6}; printf("%d\n",a[3]); f(a,6); printf("%d\n",a[3]); return 0; } /* 4 88 */指針變量的運算 指針變量不能相加,不能相乘,也不能相除,只能相減 如果兩個指針變量指向的是同一塊連續空間中的不同存儲單元,則這兩個指針變量才可以相減
# include <stdio.h> int main(void) { int i = 5; int j = 10; int *p = &i; int *q = &j; int a[5]; p = &a[1]; q = &a[4]; printf("p和q所指向的單元相隔%d個單元\n",q-p); //p-q沒有實際意義 return 0; }一個指針變量到底占幾個字節【非重點】 預備知識: sizeof(數據類型) 功能:返回值就是該數據類型所占的字節數 例子:sizeof(int) = 4 sizeof(char) = 1 sizeof(double) = 8 sizeof(變量名) 功能:返回值是該變量所占的字節數 假設p指向char類型變量(1個字節) 假設p指向char類型變量(4個字節) 假設p指向char類型變量(8個字節) p q r本身所占字節數是否一致? 答案:一致 總結: 1.一個指針變量,無論它所指向耳朵變量占幾個字節 該指針變量本身只占四個字節 2.一個變量的地址使用該變量首字節的地址來表示 指針和二維數組 3.指針和函數 4.指針和結構體 5.多級指針
//多級指針 # include <stdio.h> int main(void) { int i = 10; int *p = &i; int **q = &p; int ***r = &q; /* *r = q->**r = *q = p->***r = **q = *p = i */ //r = &p; //因為r是int ***類型,r只能存放int **類型變量的地址 printf("i = %d\n",***r); return 0; }
//多級指針 # include <stdio.h> void f(int **q) //*q就是p { } void g() { int i = 10; int *p = &i; f(&p); //p是int *類型,&p是int ** 類型 } int main(void) { g(); return 0; }專題: 動態內存分配【重點難點】
傳統數組的缺點: 1.數組的長度必須事先指定,且只能是常整數,不能是變量 例子: int a[5]; //OK int len = 5;int a[len];//error 2.傳統形式定義的數組,該數組的內存程序員無法手動釋放 在一個函數運行期間,系統為該函數中的數組所分配的空間會一直存在,直到該函數運行完畢時,數組的空間才會被系統釋放 3.數組的長度不能在函數運行的過程中動態的擴充或縮小 數組的長度一旦定義,其長度就不能再更改 4.A函數定義的數組在A函數運行期間可以被其他函數使用,但A函數運行完畢之後,A函數中的數組無法再被其他函數使用 傳統方式定義的數組不能跨函數使用 為什麽需要動態分配內存 動態數組很好的解決了傳統數組的這4個缺點 傳統數組也叫靜態數組 動態內存分配舉例--動態數組的構造
/* malloc是memory(內存) allocate(分配)的縮寫 */ # include <stdio.h> # include <malloc.h> //不能省 int main(void) { int i = 5; //分配了4個字節 靜態分配 int *p = (int *)malloc(4);//12行 /* 1.要使用malloc函數,必須添加malloc.h這個頭文件 2. mallo0c函數只有一個形參,並且形參是整型 3.4表示請求系統為本程序分配4個字節 4.malloc函數只能返回第一個字節的地址 5. 12行分配了8個字節, p變量占4個字節,p指向的內存也占4個字節 6.p本身所占的內存是靜態分配的,p所指向的內存是動態分配的 */ *p = 5;//*p代表的就是一個int變量, //只不過*p這個整型變量的內存分配方式和11行的不同 free(p); //free(p)表示把p所占的內存給釋放掉 // p本身的內存是靜態的,不能由程序員手動釋放 printf("同誌們好!\n"); return 0; }
# include <stdio.h> # include <malloc.h> int main(void) { int len; int *pArr; int i; //動態的構造一維數組 printf("請輸入您要存放的元素的個數:"); scanf("%d",&len); pArr = (int *)malloc(4 * len); //對一維數組進行操作 for(i = 0;i < len;++i) scanf("%d",&pArr[i]); //對一維數組進行輸出 printf("一維數組的內容是:\n"); for(i = 0;i < len;++i) printf("%d\n",pArr[i]); free(pArr); //釋放掉動態分配的數組 return 0; }靜態內存和動態內存的比較 靜態內存是由系統自動分配,由系統自動釋放 靜態內存是在棧分配的 動態內存是由程序員手動分配,手動釋放 動態內存是在堆分配的 跨函數使用內存的問題 靜態變量不能跨函數使用
# include <stdio.h> void f(int **q) //q也是個指針變量, //無論q是什麽類型的指針變量,都只占4個字節 { int i = 5; //*q等價於p q和**q都不等價於p //*q = i; //error 因為*q = i;等價於p = i,這是錯誤的 *q = &i; //p = &i; p = *q; --> *q = &i; } int main(void) { int *p; f(&p); //printf("%d\n",*p); //本語句語法沒有問題,但邏輯有問題 ,它是靜態分配的 return 0; }
動態內存可以跨函數使用
# include <stdio.h> # include <malloc.h> void f(int **q) { *q = (intn *)malloc(sizeof(int)); //sizeof(數據類型) 返回值是該數據類型所占的字節 **q = 5; //*p = 5; } int main(void) { int *p; f(&p); printf("%d\n",*p); //沒有錯誤,函數沒有終止 ,因為是動態分配的 return 0; }
C語言之指針