【问题标题】:Malloc function in C errors with pointers带有指针的 C 错误中的 Malloc 函数
【发布时间】:2015-03-14 09:09:59
【问题描述】:

我创建了这个函数,它应该创建一个随机生成的二叉树,它工作正常,但是在函数的末尾 root == 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;
}

【问题讨论】:

  • C是传值,你需要一个指向creaAlbero中的指针参数的指针来修改main中的root对象。
  • 代码需要检查调用 malloc 的返回值以确保操作成功
  • 如果 "if ((int)(rand()%n)==0)" 的结果从不为 0,则函数:'creaAlbero' 可以永远递归
  • @user3629249 在我有限制之前这是真的,但我注意到“n”超过 5 是非常罕见的,所以我把它拿掉了

标签: c function pointers malloc binary-tree


【解决方案1】:

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;
}

【讨论】:

    【解决方案2】:

    creaAlbero(ramo *root, int n) 是一个函数,它获取指向ramo 的指针的副本。然后它继续用这个指针副本做一些事情,然后返回。 main 然后查看 原始 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
    

    Paul Roub's answer 还提出了另一个好主意:从函数中返回ramo*,而不是将其作为可变参数。到目前为止,它更简单、更直观。

    【讨论】:

      【解决方案3】:

      您将root 设置为NULL

      ramo *root=NULL;
      

      然后将其副本传递给creaAlbero()

      creaAlbero(root, 1);
      

      修改副本

      root = malloc(sizeof(ramo));
      

      然后返回。原来的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

      【讨论】:

        猜你喜欢
        • 2019-04-23
        • 1970-01-01
        • 1970-01-01
        • 2012-03-14
        • 2015-06-16
        • 2022-11-11
        • 1970-01-01
        • 2021-05-12
        • 1970-01-01
        相关资源
        最近更新 更多