带有指针的 C 错误中的 Malloc 函数

Malloc function in C errors with pointers

我创建了这个函数,它应该创建一个随机生成的二叉树,它工作正常但在函数的末尾根 == NULL,我不明白为什么!

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

#define MAX_B 7

typedef struct _ramo{
    int nbanane;
    struct _ramo *dx;
    struct _ramo *sx;
}ramo;

void creaAlbero(ramo *root, int n){
    printf("%d\n",n);
    root = malloc(sizeof(ramo));
    root->nbanane=rand()%MAX_B;
    printf("BANANA! %d\n",root->nbanane);
    root->dx=NULL;
    root->sx=NULL;
    if ((int)(rand()%n)==0)
        creaAlbero(root->dx, n+1);
    if ((int)(rand()%n)==0)
        creaAlbero(root->sx, n+1);
 }

int main(){
    srand((unsigned int)time(NULL));
    ramo *root=NULL;
    creaAlbero(root, 1);
    if (root==NULL) {
        printf("EMPTY!!");
    }
    return 0;
}

您将 root 设置为 NULL:

ramo *root=NULL;

然后将它的副本传递给 creaAlbero():

creaAlbero(root, 1);

修改副本

root = malloc(sizeof(ramo));

然后 returns。原来的 root 仍然是 NULL,因为没有改变它。

考虑从 creaAlbero() 返回 root:

ramo * creaAlbero(int n){
  printf("%d\n",n);

  ramo *root = malloc(sizeof(ramo));
  root->nbanane=rand()%MAX_B;
  printf("BANANA! %d\n",root->nbanane);
  root->dx=NULL;
  root->sx=NULL;

  if ((int)(rand()%n)==0)
    root->dx = creaAlbero(n+1);
  if ((int)(rand()%n)==0)
    root->sx = creaAlbero(n+1);

  return root;
}

int main(){
  srand((unsigned int)time(NULL));
  ramo *root=NULL;
  root = creaAlbero(1);
  if (root==NULL) {
    printf("EMPTY!!");
  }
  return 0;
}

示例:https://ideone.com/dXiv8A

creaAlbero(ramo *root, int n) 是一个函数,它获取指向 ramo 的指针的副本。然后它继续用这个指针副本做一些事情,然后是 returns。 main 然后查看 original root 变量的值,(显然)从未更改过。

如果你想让函数修改传入的值,你必须通过指针传递对象。澄清一下:如果你想让一个函数修改一个指针,该函数必须将一个指针作为参数指向一个指针指向一个事物:

void creaAlbero(ramo **rootptr, int n){     //pass rootptr by pointer     
    *rootptr = malloc(sizeof(ramo)); //modify pointer pointed at by rootptr
    ramo* root = *rootptr; //make local copy of value for ease of use
    //rest of your code here
}
int main(){
    ramo *root=NULL;
    creaAlbero(&root, 1);  //pass by pointer

还提出了另一个绝妙的想法:return 来自函数的 ramo* 而不是将其作为可变参数。到目前为止,它更简单、更直观。

root 按值传递给 creaAlbero。在 creaAlbero 中对 root 所做的任何更改都只是局部修改。他们不会更改 main 中 root 的值。更好的选择是将 creaAlbero 的签名更改为:

ramo* creaAlbero(int n){
   printf("%d\n",n);
   ramo* root = malloc(sizeof(ramo));
   root->nbanane=rand()%MAX_B;
   printf("BANANA! %d\n",root->nbanane);
   root->dx=NULL;
   root->sx=NULL;
   if ((int)(rand()%n)==0)
      root->dx = creaAlbero(n+1);
   if ((int)(rand()%n)==0)
      root->sx = creaAlbero(n+1);

   return root;
}

并将用法更改为:

int main(){
   srand((unsigned int)time(NULL));
   ramo *root = creaAlbero(1);
   if (root==NULL) {
      printf("EMPTY!!");
   }
   return 0;
}