#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]會出現垃圾數據,會報錯
}
}