標籤:
//函式宣告
int max(int a, int b);
char * getString();
int main(int argc, const char * argv[]) {
//////////////////Lesson 10 動態記憶體管理 課堂筆記 和 練習
///////複習上周所學
/////////常量和變數的區別:
//常量中的內容不能被修改,只能訪問;
//變數中儲存的資料時可以隨時修改的。
//
//const 關鍵字的作用: 修飾變數不可改變。當做常量使用
// const int a = 10;
////////以下變數誰可不變
//口訣:看const修飾誰, 誰就不可變, 將資料類型 int 去掉 (const後面跟的變數,*也是一體的)
// int b = 30;
// const int *p1 = &b; //*p1不可變; p1指標變數,*p1指標變數指向的儲存空間。const 修飾*p1, 不能通過指標變數*p1修改指向的儲存空間上的資料,但是p1可以重新賦值。
//
// int *const p2 = &b;//p2不可變,const修飾p2,p2中儲存的資料不可更改,但是可以通過指標變數p2(使用*p2),修改指向的空間上的資料。
//
// int const *p3 = &b;//*p3不可變,同p1
//
// const int *const p4 = &b;//p4,*p4不可變
/////////不同資料類型定義的變數所儲存的內容:
//int, short, long: 儲存整數,整型資料。
//float, double:儲存小數,浮點型資料。
//char:字元型資料。
//char *, int *, short *: 儲存地址
//struct student: 儲存結構體成員資訊
//struct student * :儲存結構體變數的地址
/////////指標數組
//常量區上儲存的資料不可更改。
// char *str1 = "iPhone"; //str1儲存常量字串 iPhone 首地址;
//
// char *str2 = "Rose";
// char *str3 = "Tom";
// char *str4 = "Jack";
// char *str5 = "Android";
//
// //交換指標變數
// char *temp = str2;
// str2 = str3;
// str3 = temp;
// printf("%s \n", str3);
//
//
// char *strings[5] = {"iPhone", "Rose", "Tom", "Jack", "Android"};
// //strings[0] == str1
//
//
// char *tp = strings[1];
// strings[1] = strings[2];
// strings[2] = tp;
//
// printf("%s \n", strings[2]);
//
// printf("%p, %p", str1, strings[0]); //同一個字串,是一個地址
////////// * 的作用
// int c = 10;
// int *p = &c; //定義指標變數時,*的作用只是為了告訴編譯器,後面的變數是一個指標變數,用來儲存地址。
//
// *p = 30; //此時,* 的作用,是根據指標變數找到指向的儲存空間,並且儲存資料30
//
// printf("%d \n", *p);//同上
//
////////////////////動態記憶體
//記憶體中的5分區
//1.棧區:主要存放局部變數或者數組,定義在函數內部,當函數調用時開闢空間,當函數結束後回收空間,記憶體有 系統 進行分配和回收。
//2.堆區:堆區記憶體由 開發人員 手動開闢,手動釋放。
//3.全域、靜態區:存放全域變數,以及靜態變數; 程式運行時,開闢空間,程式運行結束空間回收。由 系統 進行管理。
//4.常量區:存放常量;整型,浮點型,字元型,字串型; 常量區空間上得內容不可修改,read-only
//5.代碼區:存放程式編譯之後形成的CUP指令,告訴電腦程式如何運行。
//////
// int a = 10, b = 20;
//
// printf("%d\n", max(a, b));
//
// printf("%s", getString());
//
////////
//如何在堆區空間上存放資料。
//如何在堆區開闢空間
//malloc在堆區開闢n個位元組大小的空間,並且返回空間的首地址。傳回值類型void *泛型,代表任意指標的類型。
//如果申請 8 個位元組的空間, 使用不同的指標類型變數接收, 儲存的資料大小不同。
//char *: 8個字元
//int *: 2個整數
//short *: 4個整數
//long *: 1個整數
// char *p = malloc(7); //手動開闢空間
//
// strcpy(p, "iPhone");
// printf("%s\n", p);
//
// strcpy(p, "Apple");
// printf("%c\n", *(p + 3));
//
// free(p); //手動釋放空間, 釋放時需要給定開始地址; 釋放只是把空間還給系統,屬於標記刪除,不清楚內容。
// printf("%p\n", p); //雖然釋放了空間,但是p存的地址並沒有清空
// printf("%s\n", p);
//
// p = NULL;//清null 指標變數中得地址,指向無效的空間
//
/////堆區空間常見的問題:
/*
1.野指標錯誤:訪問一塊沒有許可權的空間,沒有獲得空間的使用權。存在安全隱患;解決方案:當把空間還給系統之後,將指標變數中儲存的地址清空 即:賦值NULL
2.過度釋放:對一塊空間free多次,過度釋放會立即導致crash.
3.記憶體泄露:空間沒有及時的釋放,造成記憶體堆積。就是沒有free; 安全隱患.
*/
//開闢空間儲存5個整數, 賦值10 - 20
// int *a = (int*)malloc(sizeof(int) * 5);
//
// for (int i = 0; i < 5; i++) {
// *(a + i) = arc4random() % (20 - 10 + 1) + 10;
// printf("%d ", *(a + i));
// }
//
// for (int i = 0; i < 5 - 1; i++) {
// for ( int j = 0; j < 5 - 1 - i; j++) {
// if (*(a + j) < *(a + j + 1)) {
// int temp =*( a + j);
// *(a + j) = *(a + j + 1);
// *(a + j + 1) = temp;
// }
// }
// }
// printf("\n");
// for (int i = 0; i < 5; i++) {
// printf("%d ", *(a + i));
// }
//
// free(a);
// a = NULL;
// 有?字串,其中包含數字,提取其中的數字.要求動態分配記憶體儲存
// char str[]= "lan5ou2015032056", *p = NULL;
//
// char *a[20] = {0};
// int count = 0;
// int i = 0, j = 0;
////方法1
// while (str[i] != ‘\0‘){
// if (str[i] >= ‘0‘ && str[i] <= ‘9‘) {
// a[j] = (char*) malloc(sizeof(char));
// count++;
// a[j] = &str[i];
// j++;
// }
// i++;
// }
// for (int i = 0; i < count; i++) {
// printf("%c ", *(a[i]));
// }
/////方法2
// // 獲得數字個數
// i = 0;
// while (str[i] != ‘\0‘){
// if (str[i] >= ‘0‘ && str[i] <= ‘9‘) {
// count++;
// }
// i++;
// }
// //開闢空間
// char *num = malloc(count + 1);
// //儲存字元
// j = 0;
// i = 0;
// while (str[i] != ‘\0‘){
// if (str[i] >= ‘0‘ && str[i] <= ‘9‘) {
// *(num + j) = str[i];
// j++;
// }
// i++;
// }
// *(num + j) = ‘\0‘;
// printf("%s ", num);
// free(num);
// num = NULL;
//方法3
// i = 0, j = 0;
// while (str[i] != ‘\0‘){
// if (str[i] >= ‘0‘ && str[i] <= ‘9‘) {
// p = realloc(p, sizeof(char));
// count++;
// *(p + j) = str[i];
// j++;
// }
// i++;
// }
//
// printf("數字個數:%d, %s ",count, p);
// free(p);
// p = NULL;
//2. 輸?入3個學員的姓名,動態分配記憶體儲存學員姓名,並在最後輸出
//儲存3個單詞,意味著需要開闢3次空間,每次開闢空間都會返回對應的首地址, 所有為了儲存3個地址,定義指標數組儲存。
// char *word[3] = {0};
// char temp[20] = {0}; //儲存控制台輸入的字串
//
// for (int i = 0; i < 3; i++) {
// printf("\nInput [%d] name :", i + 1);
// scanf("%s",temp);
// word[i] = malloc(strlen(temp) + 1);//根據輸入的字串動態在堆區分配空間
// strcpy(word[i], temp);
// }
//
// for (int i = 0; i < 3; i++) {
// printf("%s ", *(word + i));
// free(word[i]);
// word[i] = NULL;
// }
////////其他記憶體配置函數
//////calloc(n, size_t) c---clear 多了一步空間資料的清理操作,但是清理操作效率較低。
// //分配n個size?大?小的空間,並且把該記憶體上的所有位元組清零。 分配n個size大小的空間
// int *ptr = calloc(5, 4);
//
// free(ptr);
// ptr = NULL;
//
//
// //////realloc 記憶體重新分配函數
// char *pstr = malloc(10);
// //10個空間不夠,重新分配20個,不是追加
// char *pstr1 = realloc(pstr, 200); //工作原理:先以之前的開始地址作為基準,重新分配新的空間,如果此時發現剩餘空間不足,會尋找新的空間。此時返回的地址,就和之前不一樣的,另外realloc內部整合了將之前空間free的操作。
// printf("%p, %p", pstr, pstr1);
// free(pstr1); //只需釋放realloc的空間即可。
// pstr1 = NULL;
// pstr = NULL;
//
///////記憶體操作函數
// void *memset(void *s , int c , size_t n)
// 從s指向的記憶體開始初始化n個位元組的內容為c
// int memcmp(const void *buf1, const void *buf2, unsigned int count)
//
// ?比較buf1和buf2指向的記憶體是否相同,?比較count個位元組
// void *memcpy(void *dest,const void*source , size_t n)
//
// 從source指向的記憶體開始拷?貝到dest,拷?貝n個位元組
// 定義兩個整型指標,分別?用malloc、calloc對其分配空間儲存3個元 素,malloc分配的空間?用memset清零,隨機對數組進?行賦值隨機範 圍1-3,賦值後?用memcmp?比較兩個數組。如果相同列印Good!否則 列印Failed...
//
// int *ip1 = (int *)malloc(3 * sizeof(int));
// int *ip2 = (int *)calloc(3, 4);
//
// memset(ip1, 0, 12); //清 0 操作
//
// for (int i = 0; i < 3; i++) {
// *(ip1 + i) = arc4random() % 3 + 1;
// *(ip2 + i) = arc4random() % 3 + 1;
// printf("%d %d\n",*(ip1 + i), *(ip2 + i));
//
// }
// if ( memcmp(ip1, ip2, 1) == 0) {
// printf("GOOD");
// }else{
// printf("Failed");
// }
//
return 0;
}
//函數實現
int max(int a, int b){
return a > b ? a : b;
}
//char string[] = "Welcome to Lanou iOS!"; //放在這裡是可以,不過不太安全
char *getString(){
// char string[] = "Welcome to Lanou iOS!"; // //數組string,是在函數內部定義的,屬於局部變數,儲存在棧區,當函數執行結束,數組空間被系統回收。外界拿到地址,將訪問一塊已經回收的空間。所以,要想安全的返回,必須保證返回之後空間還在。
// static char string[] = "Welcome to Lanou iOS!"; //設定成靜態數組
char *string = "Welcome to Lanou iOS!"; //返回的是常量區Welcome 。。。。,首地址;
return string;
}
iOS開發之c語言基礎Lesson-10 動態記憶體管理 上課筆記 與 試題練習