C 在函数内部创建的动态内存

C 在函数内部创建的动态内存,c,pointers,C,Pointers,我想知道这段代码无法工作的技术原因(内存方面): #include <stdio.h> #include <stdlib.h> int* fun(int*); int main() { int a=5; int* ptr; // ptr=(int*)malloc(sizeof(int)); fun(ptr); a=*ptr; printf("\n the val of a is:%d",a); return 0; } void fun(

我想知道这段代码无法工作的技术原因(内存方面):

#include <stdio.h>
#include <stdlib.h>

int* fun(int*);
int main()
{
  int a=5;
  int* ptr;
  //  ptr=(int*)malloc(sizeof(int));
  fun(ptr);
  a=*ptr;

  printf("\n the val of a is:%d",a);
  return 0;
}

void fun(int* ptr)
{

  ptr = (int*)malloc(sizeof(int));
  *ptr = 115;


}
#包括
#包括
int*乐趣(int*);
int main()
{
INTA=5;
int*ptr;
//ptr=(int*)malloc(sizeof(int));
乐趣(ptr);
a=*ptr;
printf(“\n a的val为:%d”,a);
返回0;
}
虚无乐趣(int*ptr)
{
ptr=(int*)malloc(sizeof(int));
*ptr=115;
}
为什么这行不通?我认为堆(更重要的是地址)是堆栈中所有函数变量的公共部分

还有,为什么会这样呢。
如果我对函数fun中的内存分配进行注释,并取消对main中的内存分配的注释。它工作正常。

如果要更改指针,需要在main中传递指针的地址:

fun(&ptr);
(当然,适当地改变
fun

目前,它正在函数内部更改局部变量
ptr
,当然,这种更改不会神奇地出现在其他任何地方。

函数参数
fun()
是传递到
fun()
的变量的副本。所以当你这样做的时候:

ptr = (int*)malloc(sizeof(int)); 
*ptr = 115;
你只需更改副本。您应该更改函数签名:

int* fun(int** ptr) 
{ 
     *ptr = (int*)malloc(sizeof(int)); 
     **ptr = 115; 
} 

并相应地更改调用方式。

您正在通过值将
ptr
传递到
fun
fun
将收到一份将被修改的
ptr
副本。您需要通过
ptr
作为
int**

void fun(int** ptr)
{
   *ptr = (int*)malloc(sizeof(int));
   **ptr = 115;
}
并称之为:

fun(&ptr);

(我还从
fun
中删除了返回值,因为它没有被使用)

变量
int*ptr
通过值传递给函数
fun
。因此,使用
ptr=(int*)malloc(sizeof(int)),在函数内部分配给
ptr
的值不会反映在函数外部。所以当你做
a=*ptr
main()
中,您试图使用未初始化的指针。如果您想在函数外部反映对ptr所做的更改,那么您需要将fun的签名更改为
fun(int**ptr)
,并执行
*ptr=(int*)malloc(sizeof(int))

在C中,所有内容都是通过值传递的

传递给fun()的是main()中指针的副本

这意味着ptr的拷贝针对已分配的内存,并且该内存设置为115

main()中的ptr仍然指向未定义的位置,因为它从未被分配

尝试将指针传递到该指针,以便在
fun()
中可以访问指针本身:

#include <stdio.h>
#include <stdlib.h>

int* fun(int**); // <<-- CHANGE
int main()
{
    int a=5;
    int* ptr;
    //  ptr=(int*)malloc(sizeof(int));
    fun(&ptr); // <<-- CHANGE
    a=*ptr;

    printf("\n the val of a is:%d",a);
    return 0;
}

int* fun(int** another_ptr) // <<-- CHANGE
{

    *another_ptr = (int*)malloc(sizeof(int)); // <<-- CHANGE
    **another_ptr = 115; // <<-- CHANGE
    return *another_ptr;
}

编辑:我重命名了
fun()
中的变量,以明确它与
main()
中使用的变量不同。相同的名称在这里没有任何意义。

您对这里的几件事感到困惑,但编写函数的一种简单方法是:

int * fun()
{
  int * ptr = (int*)malloc(sizeof(int));
  * ptr = 115;
  return ptr;
}
您现在负责释放内存,因此在main()中:

另一种方法是将apointer(指向指针的指针)的地址传递给函数:

void fun( int ** pp )
{
  * pp = (int*)malloc(sizeof(int));
  ** pp = 115;
}
那么main()中的代码如下所示:

int * ip;
fun( & ip );
printf( "%d", * ip );
free( ip );

我想您可以看到第一个函数使用起来更简单。

请记住,如果希望函数修改参数的值,则必须传递指向该参数的指针。这适用于指针值;如果希望函数修改指针值(而不是指针指向的对象),则必须向该指针传递指针:

void fun (int **ptr)
{
  /**
   * Do not cast the result of malloc() unless you are 
   * working with a *very* old compiler (pre-C89).  
   * Doing so will supress a valuable warning if you 
   * forget to include stdlib.h or otherwise don't have 
   * a prototype for malloc in scope.
   *
   * Also, use the sizeof operator on the item you're
   * allocating, rather than a type expression; if you
   * change the base type of ptr (say from int to long),
   * then you don't have to change all the corresponding
   * malloc() calls as well.
   *
   * type of   ptr = int **
   * type of  *ptr = int *
   * type of **ptr = int
   */  
  *ptr = malloc(sizeof **ptr);
  *ptr = 115;
}

int main(void)
{
  int *p;
  fun(&p);
  printf("Integer value stored at %p is %d\n", (void *) p, *p);
  return 0;
}

顺便说一句,您的示例中有一个类型不匹配;初始声明
fun
返回
int*
,但定义返回void

这是一个非常常见的错误,我记得很久以前我自己也做过同样的事情(在一个遥远的星系里;)@sharptooth:是的,如果malloc在游戏中,这将是一个传递值()。但是如果malloc是在main()中生成的,那么它仍然是一个传递值。你能告诉我为什么一个可以工作而另一个不能吗?因为在一个中,你初始化指针指向正确的内存,然后复制指针,并将复制指向的设置为115。在另一种情况下,复制未初始化的指针,初始化副本以指向右侧内存,并将副本指向的内容设置为115。第二种情况的区别在于原始指针仍然是uninitialized@Devsolar:是,如果malloc位于fun()中,则它将是一个传递值。但是如果malloc是在main()中生成的,那么它仍然是一个传递值。你能告诉我为什么一个人会工作而一个人不会吗?一切都是价值的传递!重新阅读代码中的第一行:假设您将main()中的
ptr
初始化为0x12345678或其他。注释掉的行调用
malloc()
,并将其返回值分配给
ptr
,使其指向
malloc()分配的内存位置。
——相反,函数
fun()
,接收
ptr
(指向0x12345678),调用
malloc()
,将其返回值指定给
ptr
的副本,然后返回。(错误地没有返回播发的
int*
。)函数返回后,您又在处理真正的
ptr
,它仍然指向0x12345678…另请参见更新的答案。@DevSolar:哇,我完全忘了返回语句。对不起。。。非常感谢。我一心想在不使用双指针的情况下找到答案。@Andreas:是的,如果malloc在fun()中,它将是一个传递值。但是如果malloc是在main()中生成的,那么它仍然是一个传递值。你能告诉我为什么一个会工作而一个不会吗?
int * ip;
fun( & ip );
printf( "%d", * ip );
free( ip );
void fun (int **ptr)
{
  /**
   * Do not cast the result of malloc() unless you are 
   * working with a *very* old compiler (pre-C89).  
   * Doing so will supress a valuable warning if you 
   * forget to include stdlib.h or otherwise don't have 
   * a prototype for malloc in scope.
   *
   * Also, use the sizeof operator on the item you're
   * allocating, rather than a type expression; if you
   * change the base type of ptr (say from int to long),
   * then you don't have to change all the corresponding
   * malloc() calls as well.
   *
   * type of   ptr = int **
   * type of  *ptr = int *
   * type of **ptr = int
   */  
  *ptr = malloc(sizeof **ptr);
  *ptr = 115;
}

int main(void)
{
  int *p;
  fun(&p);
  printf("Integer value stored at %p is %d\n", (void *) p, *p);
  return 0;
}