一、基本特性
1、 realloc()函數可以重用或擴展以前用malloc()、calloc()及realloc()函數自身分配的內存。
2、 realloc()函數需兩個參數:一個是包含地址的指針(該地址由之前的malloc()、calloc()或realloc()函數返回),另一個是要新分配的內存字節數。
3、 realloc()函數分配第二個參數指定的內存量,並把第一個參數指針指向的之前分配的內容復制到新配的內存中,且復制的內容長度等於新舊內存區域中較小的那一個。即新內存大於原內存,則原內存所有內容復制到新內存,如果新內存小於原內存,只復制長度等於新內存空間的內容。
4、realloc()函數的第一個參數若為空指針,相當於分配第二個參數指定的新內存空間,此時等價於malloc()、calloc()或realloc()函數。
5、如果是將分配的內存擴大,則有以下3種情況:
如果當前內存段后面有需要的內存空間,則直接擴展這段內存空間,realloc()將返回原指針。
如果當前內存段后面的空閑字節不夠,那么就使用堆中的第一個能夠滿足這一要求的內存塊,將目前的數據復制到新的位置,並將原來的數據塊釋放掉,返回新的內存塊位置。
如果申請失敗,將返回NULL,此時,原來的指針仍然有效。
二、注意事項
1、第一個參數要么是空指針,要么是指向以前分配的內存。如果不指向以前分配的內存或指向已釋放的內存,結果就是不確定的。
2、 如果調用成功,不管當前內存段后面的空閑空間是否滿足要求,都會釋放掉原來的指針,重新返回一個指針,雖然返回的指針有可能和原來的指針一樣,即不能再次釋放掉原來的指針。
今天就在釋放原指針(即realloc()函數的第一個參數)這個地方犯了一個錯誤。下面是測試程序。測試程序的功能非常簡單:實現在一個按升序排序的數組中查找x應插入的位置,將x插入數組中,使數組元素仍按升序排列。
1 #include<stdio.h> 2 #include<stdlib.h> 3 int main() 4 { 5 int n = 0; 6 int i = 0; 7 int index = 0; 8 int insert_data = 0; 9 int *pNumber = NULL; 10 int *pNewArray = NULL; 11 printf("Input array size:\n"); 12 scanf("%d", &n); 13 pNumber = (int*)calloc(n, sizeof(int)); 14 if(pNumber == NULL) 15 { 16 printf("Not enough memory\n"); 17 exit(0); 18 } 19 //輸入插入前已按升序排序的數組元素提示信息 20 printf("Input array:\n"); 21 for(i = 0; i < n; i++) 22 { 23 scanf("%d", pNumber+i); 24 } 25 //輸入待插入的元素x提示信息: 26 printf("Input x:\n"); 27 scanf("%d", &insert_data); 28 //確定待插入位置的索引值 29 for(i = 0; i < n; i++) 30 { 31 if(insert_data < *(pNumber+i)) 32 { 33 index = i; 34 break; 35 } 36 } 37 //用realloc()新分配一塊內存,用於存儲原數組和新插入的值 38 pNewArray = (int*)realloc(pNumber, (n+1)*sizeof(int)); 39 if(pNewArray == NULL) 40 { 41 printf("Not enough memory\n"); 42 exit(0); 43 } 44 //free(pNumber); 45 //輸出新分配的內存空間的值,查看是否實現了復制 46 for(i = 0; i < n+1; i++) 47 { 48 printf("%4d", pNewArray[i]); 49 } 50 printf("\n"); 51 //待插入位置及后面的所有數據依次向后移1位 52 for(i = n; i > index; i--) 53 { 54 *(pNewArray+i) = pNewArray[i-1]; 55 } 56 *(pNewArray + index) = insert_data; 57 printf("After insert %d:\n", insert_data); 58 for(i = 0; i < n+1; i++) 59 { 60 printf("%4d", *(pNewArray+i)); 61 } 62 free(pNewArray); 63 return 0; 64 }
注意代碼44行出,如果注釋掉,則結果正確。如果不注釋掉則錯誤。說明上面所述的注意事項中的第2條是正確的。下面是測試用例及結果。


左側圖片為注釋掉代碼44行的正確結果,右側圖片為未注釋掉44行代碼的錯誤結果。
之前一直覺得這個地方沒有什么,沒想到今天寫程序時候在這個地方掉坑里面了。越是這種不注意的小地方越容易犯錯。引以為戒。
