2010-04-12 215 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; 
    }