#include <stdio.h> #include <stdlib.h> //malloc free #include <windows.h> //sleep void main1(){ //int a[1024*1024*1000]; //數組只能處理小數量的數據 int num =100; //int b[num]; 數組的大小必須明確,num是變量,隨時可以變化 //數組內存這種分配機制就稱為靜態分配,數組使用完成后系統自動回收 //動態內存分配 /* malloc和free是C標准庫中提供的兩個函數,用以動態申請和釋放內存,malloc()函數的基本調用格式為: void *malloc( unsigned int size ); 參數size是個無符號整型數,用戶由此控制申請內存的大小,執行成功時,系統會為程序開辟一塊大小為size個內存字節的區域,並將該區域的首地址返回, 用戶可利用該地址管理並使用該塊內存,如果申請失敗(比如內存大小不夠用),返回空指針NULL。 malloc()函數返回類型是void*,用其返回值對其他類型指針賦值時,必須進行顯式轉換。 size僅僅是申請字節的大小,並不管申請的內存塊中存儲的數據類型,因此,申請內存的長度須由程序員通過“長度×sizeof(類型)”的方式給出,舉例來說: int* p=(int*) malloc(5* sizeof(int) ); Free就是釋放內存,例如free(p) */ //輸入一個數字,並用float類型的數據初始化,形式:1.000,2.000 ... f float f; scanf("%f",&f); void *pVoid = malloc(f * sizeof(float)); //malloc返回值是空指針 float *pFloat = (float *)pVoid; //下標法 for (int i = 0; i < f; ++i) { pFloat[i] =i+1; printf("%f,%p \n",pFloat[i],&pFloat[i]); } //指針法 printf("\n\n\n"); float *p =pFloat; int fInt = (int)f; for ( int i = 0; p < pFloat + fInt; ++i,++p) { // p < pFloat + fInt此處的條件要注意,既然循環了,就要用p去循環, PFloat是不變的,切忌寫成 p < p + fInt,這樣的話 < 兩邊的p就一起動了 *p = i+1; printf("%f,%p \n",*p,p); } free(pVoid); //釋放內存 pVoid是地址,只能free一次, NUll指針可以釋放多次 } void main2(){ float f =3.0f; int a =(int) f; printf("%d,%f",a,a); //3,0.000000 一個很小的整數,按照%f來解析,會打印出 0.0000000 } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void main4(){ int n; scanf("%d",&n); //double *pDouble = (double *)malloc(n * sizeof(double)); //malloc不會初始化 double *pDouble = (double *)calloc(n, sizeof(double)); //calloc自動初始化內存為0 for (double i = 0.0; i < n; ++i) { pDouble[(int)i] =i+1.0; //i 強制轉換成int printf("%lf,%p\n",pDouble[(int)i],&pDouble[(int)i]); } } void main5(){ int num; printf("please input the size of array:\n"); scanf("%d",&num); int *p = (int *)malloc(num * sizeof(int)); if(p==NULL) /*防錯處理,看內存申請是否成功*/ { printf("內存申請失敗,退出"); return; } for (int i = 0; i < num; ++i) { p[i] =i+1; printf("%d,%p\n",p[i],&p[i]); } printf("if you want to rezize the array, please input a new number:\n"); int newNum; scanf("%d",&newNum); //為已經分配的內存重新分配空間並復制內容 // realloc()函數有兩個參數:已分配的內存地址,重新分配的字節數 // void *realloc( void *ptr, size_t size ) int *newP = (int *) realloc((void *)p,newNum); //重新分配newNum字節的內存,並根據p的地址把原來malloc分配的內容復制過來 printf("after realloc, p :%d,%p\n",*p,p); // p :1,00030E58 printf("after realloc, p+5 :%d,%p\n",*(p+5),p+5); // after realloc, p+5 :13643,006D0E6C //似乎realloc后,沒有自動釋放掉p,但p的地址不變,只是所指向的類型為空指針 for (int i = num; i < newNum; ++i) { //注意因為前num個元素已經有realloc復制過來了,所以從num開始復制 newP[i] =i+1; } //打印新的分配的數組 for (int j = 0; j < newNum; ++j) { printf("%d,%p\n",newP[j],&newP[j]); } free(p); //內存釋放以后,指針的值(地址)不會變化,只是把類型取消了 free(newP); } /* please input the size of array: 3 1,00020E58 2,00020E5C 3,00020E60 if you want to rezize the array, please input a new number: 6 1,00020E58 可以看到新分配的內存空間首地址是一樣的,可以得知舊的p指針所指向的那片內存空間后面任有剩余未占用的空間,所以繼續往后分配 2,00020E5C 如果舊指針p后面沒有剩余空間了,就會另外找一片內存區域,重新分配,舊的空間就自動釋放掉 3,00020E60 4,00020E64 5,00020E68 6,00020E6C*/ void main(){ int num; printf("please input the size of array:\n"); scanf("%d",&num); int *p = (int *)malloc(num * sizeof(int)); if(p==NULL) /*防錯處理,看內存申請是否成功*/ { printf("內存申請失敗,退出"); return; } else{ for (int i = 0; i < num; ++i) { p[i] = i + 1; printf("%d,%p\n", p[i], &p[i]); } printf(" before free :%p\n",p); free(p); //free 前后p的地址不會發生改變 printf("after free :%p\n",p); p=NULL; //軟件工程規范,釋放指針后要置為NULL,可以規避釋放后再次引用和反復釋放的問題 printf("after free p[2]:%d\n",p[2]); //free之后,再次引用p[2]會出現垃圾數據,會報錯 } }