printf,scanf、malloc、realloc、calloc(與c++的new的區別)的各種用法

printf,scanf、malloc、realloc、calloc(與c++的new的區別)的各種用法

printf、scanf:

  • printf()函數是格式化輸出函數, 一般用於向標準輸出設備按規定格式輸出信息。
    printf()函數的調用格式爲: printf(“<格式化字符串>”, <參量表>)。
    格式輸出,它是c語言中產生格式化輸出的函數(在 stdio.h 中定義)。用於向終端(顯示器、控制檯等)輸出字符。格式控制由要輸出的文字和數據格式說明組成。要輸出的的文字除了可以使用字母、數字、空格和一些數字符號以外,還可以使用一些轉義字符表示特殊的含義。
    具體格式:
    int i, j;
    scanf(“%d, %d”, &i, &j);
    printf(“i=%d;j=%d”, i, j);
    return 0;

    or:
    printf(“百度百科”);
    return 0;

  • 與printf函數一樣,都被定義在頭文件stdio.h裏,因此在使用scanf函數時要加上#include

malloc、realloc、calloc:

  • malloc:

函數聲明(函數原型):

void *malloc(int size);

說明:malloc 向系統申請分配指定size個字節的內存空間。返回類型是 void* 類型。void* 表示未確定類型的指針。C,C++規定,void* 類型可以強制轉換爲任何其它類型的指針。
從函數聲明上可以看出。malloc 和 new 至少有兩個不同: new 返回指定類型的指針,並且可以自動計算所需要大小。比如:

int *p;

p = new int; //返回類型爲int* 類型(整數型指針),分配大小爲 sizeof(int);

或:

int* parr;

parr = new int [100]; //返回類型爲 int* 類型(整數型指針),分配大小爲 sizeof(int) * 100;

而 malloc 則必須由我們計算要字節數,並且在返回後強行轉換爲實際類型的指針。

int* p;

p = (int *) malloc (sizeof(int));

第一、malloc 函數返回的是 void * 類型,如果你寫成:p = malloc (sizeof(int)); 則程序無法通過編譯,報錯:“不能將 void* 賦值給 int * 類型變量”。所以必須通過 (int *) 來將強制轉換。

第二、函數的實參爲 sizeof(int) ,用於指明一個整型數據需要的大小。如果你寫成:

int* p = (int *) malloc (1);

代碼也能通過編譯,但事實上只分配了1個字節大小的內存空間,當你往裏頭存入一個整數,就會有3個字節無家可歸,而直接“住進鄰居家”!造成的結果是後面的內存中原有數據內容全部被清空。

malloc 也可以達到 new [] 的效果,申請出一段連續的內存,方法無非是指定你所需要內存大小。

比如想分配100個int類型的空間:

int* p = (int ) malloc ( sizeof(int) 100 ); //分配可以放得下100個整數的內存空間。

另外有一點不能直接看出的區別是,malloc 只管分配內存,並不能對所得的內存進行初始化,所以得到的一片新內存中,其值將是隨機的。

除了分配及最後釋放的方法不一樣以外,通過malloc或new得到指針,在其它操作上保持一致。

  • 總:
    realloc
    原型:extern void *realloc(void *mem_address, unsigned int newsize);
    用法:#include <stdlib.h> 有些編譯器需要#include <alloc.h>
    功能:改變mem_address所指內存區域的大小爲newsize長度。
    說明:如果重新分配成功則返回指向被分配內存的指針,否則返回空指針NULL。
    當內存不再使用時,應使用free()函數將內存塊釋放。
    注意:這裏原始內存中的數據還是保持不變的。
    舉例:
    // realloc.c
#include <syslib.h>
#include <alloc.h>
main()
{
char *p;
clrscr(); // clear screen
p=(char *)malloc(100);
if(p)
printf("Memory Allocated at: %x",p);
else
printf("Not Enough Memory!/n");
getchar();
p=(char *)realloc(p,256);
if(p)
printf("Memory Reallocated at: %x",p);
else
printf("Not Enough Memory!/n");
free(p);
getchar();
return 0;
}

詳細說明及注意要點:
1、如果有足夠空間用於擴大mem_address指向的內存塊,則分配額外內存,並返回mem_address
這裏說的是“擴大”,我們知道,realloc是從堆上分配內存的,當擴大一塊內存空間時, realloc()試圖直接從堆上現存的數據後面的那些字節中獲得附加的字節,如果能夠滿足,自然天下太平。也就是說,如果原先的內存大小後面還有足夠的空閒空間用來分配,加上原來的空間大小= newsize。那麼就ok。得到的是一塊連續的內存。
2、如果原先的內存大小後面沒有足夠的空閒空間用來分配,那麼從堆中另外找一塊newsize大小的內存。
並把原來大小內存空間中的內容複製到newsize中。返回新的mem_address指針。(數據被移動了)。
老塊被放回堆上。
例如:

#include <malloc.h>
char *p,*q;
p = (char * ) malloc (10);
q=p;
p = (char * ) realloc (p,20);

…………………………
這段程序也許在編譯器中沒有辦法通過,因爲編譯器可能會爲我們消除一些隱患!在這裏我們只是增加了一個記錄原來內存地址的指針q,然後記錄了原來的內存地址p,如果不幸的話,數據發生了移動,那麼所記錄的原來的內存地址q所指向的內存空間實際上已經放回到堆上了!這樣一來,我們應該終於意識到問題的所在和可怕了吧!
3、返回情況
返回的是一個void類型的指針,調用成功。(這就再你需要的時候進行強制類型轉換)
返回NULL,當需要擴展的大小(第二個參數)爲0並且第一個參數不爲NULL,此時原內存變成了“freed(遊離)”的了。
返回NULL,當沒有足夠的空間可供擴展的時候,此時,原內存空間的大小維持不變。
4、特殊情況
如果mem_address爲null,則realloc()和malloc()類似。分配一個newsize的內存塊,返回一個指向該內存塊的指針。
如果newsize大小爲0,那麼釋放mem_address指向的內存,並返回null。
如果沒有足夠可用的內存用來完成重新分配(擴大原來的內存塊或者分配新的內存塊),則返回null.而原來的內存塊保持不變。

==============================================================

void* malloc(unsigned size); void* calloc(size_t nelem, size_t elsize); 和void* realloc(void* ptr, unsigned newsize);都在stdlib.h函數庫內,是C語言的標準內存分配函數。
1. 函數malloc()和calloc()都可以用來動態分配內存空間。malloc()函數有一個參數,即要分配的內存空間的大小,malloc 在分配內存時會保留一定的空間用來記錄分配情況,分配的次數越多,這些記錄佔用的空間就越多。另外,根據 malloc 實現策略的不同,malloc 每次在分配的時候,可能分配的空間比實際要求的多些,多次分配會導致更多的這種浪費。當然,這些都和 malloc 的實現有關;calloc()函數有兩個參數,分別爲元素的數目和每個元素的大小,這兩個參數的乘積就是要分配的內存空間的大小。如果調用成功,它們都將返回所分配內存空間的首地址。
2. 函數malloc()和函數calloc()的主要區別是前者不能初始化所分配的內存空間,而後者能。
3. realloc可以對給定的指針所指的空間進行擴大或者縮小,無論是擴張或是縮小,原有內存的中內容將保持不變。當然,對於縮小,則被縮小的那一部分的內容會丟失。
4. realloc 並不保證調整後的內存空間和原來的內存空間保持同一內存地址。相反,realloc 返回的指針很可能指向一個新的地址。所以在代碼中,我們必須將realloc返回的值,重新賦值給 p :
p = (int *) realloc (p, sizeof(int) *15);

==================================================================
真正認識 realloc 的工作方式。
Posted on 2008-11-20 13:12 啊夏 閱讀(142) 評論(0) 編輯 收藏 網摘 所屬分類: c/c++

realloc 用過很多次了。無非就是將已經存在的一塊內存擴大。

char* p = malloc(1024);
char* q = realloc(p,2048);

現在的問題是我們應該如何處理指針 p。 剛開始按照我最直觀的理解,如果就是直接將 p = NULL;。 到最後只需要釋放 q的空間就可以了。

因爲最近在做個封裝。結果在做單元測試的時候發現。有時候我在 free(q); 的時候會出錯。這樣我就鬱悶了。

後來仔細一跟蹤,發現 realloc 完以後 q 和 p 的指針地址是一樣。不過有時候又不一樣。

仔細查了下資料。得到如下信息:

   1.如果 當前連續內存塊足夠 realloc 的話,只是將p所指向的空間擴大,並返回p的指針地址。 這個時候 q 和 p 指向的地址是一樣的。

   2.如果 當前連續內存塊不夠長度,再找一個足夠長的地方,分配一塊新的內存,q,並將 p指向的內容 copy到 q,返回 q。並將p所指向的內存空間刪除。

這樣也就是說 realloc 有時候會產生一個新的內存地址 有的時候不會。所以在分配完成後。我們需要判斷下 p 是否等於 q。並做相應的處理。

這裏有點要注意的是要避免 p = realloc(p,2048); 這種寫法。有可能會造成 realloc 分配失敗後,p原先所指向的內存地址丟失。

=========================================

關於realloc函數說明的補充:
函數定義:
void *realloc(void *ptr, size_t size);
上面的分析基本沒有問題,但有兩點要注意:
1.返回值可能與ptr的值不同,如果是不同的話,那麼realloc函數完成後,ptr指向的舊內存已被free掉了。
2。如果返回NULL值,則分配不成功,而原來的ptr指向的內存還沒有被free掉,要求程序顯式free.

故p = (int *) realloc (p, sizeof(int) *15);語句有這麼一個問題,
調用前p指向一個已分配成功的內存,而調用realloc時卻失敗(即返回NULL),此時,p原來指向的內存還沒有free掉,而現在又找不到地址,這樣就出現memory leak了。

關於這一點的確要注意,最好如下:
int *q
q = (int *) realloc (p, sizeof(int) *15);

if(!q) p =q;

======================================================

首先看一下下面的C程序片斷:

#include <malloc.h>

char  *p;

p = (char * ) malloc (10);

p = (char * ) realloc (p,20);

…………………………

這段程序的意思很簡單,只有稍有點C基礎的人都可以看懂。函數首先定義了一個字符型的指針p,然後爲指針p分配了一個10個字節大小的內存空間,接着將這個內存塊的大小增加到20個字節。



這裏有什麼問題嗎?上機運行一下,好像沒有問題!



是的,這樣上機運行是沒有問題的,但是這裏存在着也許我們不太注意的隱患!隱患在那裏?這就是我在本文中要詳細說明的realloc()函數了。



再看一下下面一段來自MSDN的話:

realloc returns a void pointer to the reallocated (and possibly moved) memory block. The return value is NULL if the size is zero and the buffer argument is not NULL, or if there is not enough available memory to expand the block to the given size. In the first case, the original block is freed. In the second, the original block is unchanged. The return value points to a storage space that is guaranteed to be suitably aligned for storage of any type of object. To get a pointer to a type other than void, use a type cast on the return value.

這段E文還不算是晦澀難懂,所以我就不翻譯了,大致的意思是說關於realloc返回值的。但是這裏對他的返回值分了幾種情況:

1、 返回void * 指針,調用成功。

2、 返回NULL,當需要擴展的大小(第二個參數)爲0並且第一個參數不爲NULL,此時原內存變成了“freed(遊離)”的了。

3、 返回NULL,當沒有足夠的空間可供擴展的時候,此時,原內存空間的大小維持不變。

第一種情況告訴了我們在得到需要的內存空間後需要做類型轉換的工作;

第二種情況可能只有傻瓜纔會去使用吧!

第三種情況,內存空間不夠的時候就會維持未來的大小不變。

    MSDN上面說內存空間不夠的時候就不會擴展原來的內存空間的大小,這話固然沒有錯,但是有點含糊,似乎遺漏了一種情況!我們知道,realloc是從堆上分配內存的,當擴大一塊內存空間時, realloc()試圖直接從堆上現存的數據後面的那些字節中獲得附加的字節,如果能夠滿足,自然天下太平;可如果數據後面的字節不夠的話,問題就出來了,那麼就使用堆上第一個有足夠大小的自由塊,現存的數據然後就被拷貝至新的位置,而老塊則放回到堆上。這句話傳遞的一個重要的信息就是數據可能被移動!看到這裏,也許我們已經發現一開始我給出的程序的問題了。爲了更清楚地說明問題,可以將上面的程序改成下面的形式:
#include <malloc.h>

char  *p,*q;

p = (char * ) malloc (10);

q=p;

p = (char * ) realloc (p,20);

…………………………

這段程序也許在編譯器中沒有辦法通過,因爲編譯器可能會爲我們消除一些隱患!在這裏我們只是增加了一個記錄原來內存地址的指針q,然後記錄了原來的內存地址p,如果不幸的話,數據發生了移動,那麼所記錄的原來的內存地址q所指向的內存空間實際上已經放回到堆上了!這樣一來,我們應該終於意識到問題的所在和可怕了吧!

malloc與c++中的new的區別:

malloc與new :

1 、new 建立的是一個對象,malloc 分配的是一塊內存。
2、malloc申請的是heap區的內存空間,返回的是指針。new 建立的對象你可以把它當成一個普通的對象,用成員函數訪問,不要直接訪問它的地址空間。(注意用delete釋放空間)。
3、malloc/free是C/C++中的方法(函數),new/delete是C++中的操作符。
4、使用free之前要判斷,使其free的指針是!NULL的,使用delete則無須判斷。
5、free掉的內存是該指針指向的一段內存空間,裏面應該是空的。而delete掉的內存是裏面確實存有數據或者對象的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章