简体   繁体   English

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

[英]Malloc function in C errors with pointers

I've create this function that's supposed to create a randomly generated binary tree, it works fine but at the end of the function the root == NULL, i can't understand why! 我已经创建了应该创建一个随机生成的二叉树的函数,它可以正常工作,但是在函数末尾,根== 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;
}

You set root to NULL : 您将root设置为NULL

ramo *root=NULL;

then pass a copy of it to creaAlbero() : 然后将其副本传递给creaAlbero()

creaAlbero(root, 1);

which modifies the copy 修改副本

root = malloc(sizeof(ramo));

then returns. 然后返回。 The original root is still NULL , because nothing changed it. 原始root仍然为NULL ,因为没有任何更改。

Consider returning root from creaAlbero() : 考虑从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;
}

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

creaAlbero(ramo *root, int n) is a function that takes a copy of a pointer to a ramo . creaAlbero(ramo *root, int n)是一个函数,它获取指向ramo的指针的副本。 It then proceeds to do stuff with this copy of the pointer, and then returns. 然后,它继续使用此指针副本进行操作,然后返回。 main then looks a the value of the origonal root variable, which was (obviously) never changed. 然后main会查找原始 root变量的值,该值(显然)从未改变。

If you want a function to modify a value that's passed in, you must pass the object by pointer. 如果要让函数修改传入的值,则必须通过指针传递对象。 To clarify: if you want a function to modify a pointer, the function must take as a parameter a pointer to a pointer to a thing: 需要说明的是:如果要让函数修改指针,则该函数必须将指向事物的指针的指针作为参数:

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

Paul Roub's answer also suggests another excellent idea: return the ramo* from the function instead of taking it as a mutable parameter. 保罗·鲁布(Paul Roub)的答案还提出了另一个绝妙的主意:从函数返回ramo*而不是将其作为可变参数。 It's simpler and more intuitive by far. 到目前为止,它更简单,更直观。

root is passed to creaAlbero by value. root按值传递给creaAlbero Any changes made to root in creaAlbero are only local modifications. creaAlbero中的root所做的任何更改仅是本地修改。 They don't change the value of root in main. 它们不会更改main中root的值。 A better alternative would be to change the signature of creaAlbero to: 更好的选择是将creaAlbero的签名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;
}

and change the usage to: 并将用法更改为:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM