2010-04-12 221 views
16

我在下面的代碼中存在分段錯誤,但是在將其更改爲指針指針後,它很好。有人能給我任何理由嗎?爲什麼需要指針指針來分配內存中的功能

void memory(int * p, int size) { 
    try { 
     p = (int *) malloc(size*sizeof(int)); 
    } catch(exception& e) { 
     cout<<e.what()<<endl; 
    } 
} 

它不會在主函數工作作爲打擊

int *p = 0; 
memory(p, 10); 

for(int i = 0 ; i < 10; i++) 
    p[i] = i; 

但是,它的工作原理是這樣的。

void memory(int ** p, int size) {    `//pointer to pointer` 
    try{ 
     *p = (int *) malloc(size*sizeof(int)); 
    } catch(exception& e) { 
     cout<<e.what()<<endl; 
    } 
} 

int main() 
{ 
    int *p = 0; 
    memory(&p, 10);  //get the address of the pointer 

    for(int i = 0 ; i < 10; i++) 
     p[i] = i; 

    for(int i = 0 ; i < 10; i++) 
     cout<<*(p+i)<<" "; 

    return 0; 
} 
+7

由於malloc永遠不會拋出,所以這些try塊沒有意義。 – 2010-04-12 22:27:45

+0

如果這是C,那些try塊是無效的。這實際上是C++嗎?如果是這樣,標籤需要改變。 – 2010-04-12 22:31:22

+0

@Fred,這個問題與C也有關係,即使片段是C++,正如你所指出的那樣。我添加了C++標記 – hhafez 2010-04-12 22:39:12

回答

50

因爲你想獲得一個指針值從功能完成的作業後面malloc分配內存併爲您提供該內存的地址。

在第一個示例中,您將該地址存儲在本地變量變量p中,但由於它只是參數,因此不會將其返回到主程序,因爲C/C++是傳遞值默認情況下爲 - 即使是指針。

Main  Function  malloc 

    p   p   allocated 
+---+  +---+   
| 0 |  | 0 |   A 
+---+  +---+ 

becomes... 

    p   p   allocated 
+---+  +---+   
| 0 |  | ------------> A 
+---+  +---+ 

因此當主讀取P,它的收益爲0,而不是A.

在你工作的代碼,你跟着傳遞給一個地址指針,而該地址給你的指針變量的位置在主程序中。您更新該地址的指針值,然後主程序可以查找該值作爲其內存位置 - 從而將由malloc返回的地址傳回主程序以供使用。

Main  Function  malloc 

    p   p   allocated  
+---+  +---+   
| 0 |<------- |   A 
| |  | | 
+---+  +---+ 

becomes... 

    p   p   allocated  
+---+  +---+   
| |<------- |   
| ----------------------> A 
+---+  +---+ 

並且因此主當讀P,它得到A.

+13

爲ASCII藝術+1。 8v) – 2010-04-12 22:33:25

+2

ASCII藝術有時候可以很有趣... – Amber 2010-04-12 22:36:21

+0

damnit ...我要製作漂亮的指針圖...不再有任何 – Polaris878 2010-04-12 22:36:47

7

的指針存儲在其中的數據被存儲的地址。將指針傳遞給函數意味着給它的地址爲的數據爲。但是,在撥打malloc之前,您沒有地址。因此,您需要傳遞指針的地址(即指向指針的指針)。這允許memory獲取指針p的地址,並將p設置爲指向它爲數據分配的內存區域。

+0

比Dav的更清晰,儘管看起來你們都說同一件事。你們都得票。 :) – Dustin 2010-04-12 22:29:55

1

第一個示例不起作用,因爲指針參數不是main中的指針,它只是保持相同的值。

0

你不需要使用一個指向指針,但引用指針即* &不僅僅是*

3

在C,你只有通過按值。所以你的函數內存()獲取它自己的本地副本。內存malloc()將僅分配給函數本地的p的副本。當memory()返回到main()時,main的p副本不變。在C++中,可以使用通過按引用,像這樣解決這個問題:

void memory(int*& p, int size)

在C中,使用雙指針,以實現類似的結果。

+1

應該是'*&'。 (從右側讀取,這是我以另一種方式放置空間的原因之一:'int *&p'('int *'是您正在引用的類型):) – UncleBens 2010-04-12 22:45:02

+0

不是嗎?是'int *&'來表示對指向int的指針的引用嗎?你的代碼示例是'int&*',它是一個指向int引用的指針,如果你將一個指針傳遞給一個引用,它就會失去引用的目的。或者,也許我在誤讀它......? – Dustin 2010-04-12 22:46:15

+0

@UncleBens,達斯汀:那是一個錯字,很好的結果。我將空間移到了類型旁邊。 – kbyrd 2010-04-13 03:47:07

2

在你第一次調用內存:

void memory(int * p, int size) 

意識到你正在傳遞一個VALUE內存(),而不是一個地址。因此,您將'0'的值傳遞給memory()。變量p只是無論你傳遞......在包含相同的值,但確實不到同一地址的副本...

在你的第二個功能,您傳遞的地址你的論點......相反,p指向你的變量的地址,而不僅僅是你的變量的副本。

所以,當你調用malloc像這樣:

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

要分配的malloc的返回變量p點的值。

因此,您的指針在內存()之外有效。

0

您需要一個指向指針的指針,因爲您需要返回新分配的指針的值。

有三種方式(如果你用C 2)返回值:

  • 使用指針,這裏是指針
  • 使用的參考指針,這裏是一個參考指針
  • 使用該函數的返回值,所以使內存返回INT *,而不是無效

第三種方式,肯定我的偏好。 (而不是,我不承認你也可以使用全球化,這不是第四種方式,而是一種恐怖)。

-1

我校正的代碼..讀取的評論,並都將是清楚..

#include<iostream> 
#include<conio.h> 
#include<exception> 

using namespace std; 


void memory(int* p, int size) {    //pointer to pointer` not needed 
    try{ 
     p = new int[size] ; 
    } catch(bad_alloc &e) { 
     cout<<e.what()<<endl; 
    } 
} 

int main() 
{ 
    // int *p = 0; wrong .. no memory assigned and then u are passing it to a function 
    int *p; 
    p = new int ; // p = malloc(sizeof(int)); 
    /*before using a pointer always allocate it memory else 
    you ll get frequent system crashes and BSODs*/ 
    memory(p, 10);  //get the address of the pointer 

    for(int i = 0 ; i < 10; i++) 
     p[i] = i; 

    for(int i = 0 ; i < 10; i++) 
     cout<<*(p+i)<<" "; 

    getch();  
    return 0; 
} 
0

存儲器(P,10); //得到指針的地址

這只是發送p值而不是p的地址。它發送(* p)。如果p 123的附加值和它的值50,則向函數發送50。

並在記憶功能,它使新的地址,如124新的指針,它包含50;它將分配內存並將分配的內存的開始寫入124而不是123,因此主存儲器中的p仍包含50.因此,您什麼也沒做!你可以用這個代碼來控制它。

 #include<iostream> 
    #include<conio.h> 
    #include<exception> 

    using namespace std; 


    void memory(int* p, int size) {    //*************pointer to pointer` is a must********** 
     try{ 
      p = new int[size] ; 
      p[0]=100; 
     } catch(bad_alloc &e) { 
      cout<<e.what()<<endl; 
     } 
    } 

    int main() 
    { 
     int *p = 0; ******you can do you should do this******* 
     p = new int ; 
/* p = malloc(sizeof(int)); // this just change the value inside of p it is unnecessary 
and you will lose a adress from memory :) and possibly it will be unsafe if you free p may, you just 
free one adress*/ 
     /*before using a pointer always allocate it memory else 
     you ll get frequent system crashes and BSODs*/ 
     memory(p, 10);  //get the address of the pointer//you are getting nothing 
     cout <<p[0]; 
     //we set p[0] to 100 but it will write a garbage value here. 
     //because the value inside of p didn't change at the memory function 
     //we sent just the value inside of p. 

     getch();  
     return 0; 
    }