C:通过空指针引用结构的正确方法

标签 c binary-search-tree void-pointers

我正在尝试将 Student 类型的元素(定义如下)插入到“NoArv”类型结构(定义如下)的字段“info”中。 我需要通过一个类型为“Base”的指针来执行此操作,它是一个空指针。

我尝试了下面的代码,但是在编译时,我收到了以下错误消息:

> base.c:38:19: error: dereferencing ‘void *’ pointer [-Werror]
>
     if(a.ra < (*p)->info.ra)
>                    ^
> base.c:38:19: error: request for member ‘info’ in something not a structure or union
> 
> base.c:39:16: error: dereferencing ‘void *’ pointer [-Werror]
>
       *p = (*p)->left;
>
>                 ^

我怎样才能正确取消引用这样一个指向 void 类型的指针?

我用这个调用函数:InsereBase(&base, student)

其中“base”是Base 类型的变量,“student”是Student 类型的元素。

代码:

Boolean InsertBase(Base *p, Student a) {
  while((*p) != NULL){
    if(a.ra < (*p)->info.ra)
      *p = (*p)->left;
    else if(a.ra > (*p)->info.ra)
      *p = (*p)->right;
    else
      return false;
  }

  *p = MALLOC(sizeof(NoArv));
  (*p)->info = MALLOC(sizeof(Student));
  (*p)->info.ra = a.ra;
  (*p)->info.name = a.name;

  (*p)->left = (*p)->right = NULL;

  return true;

}

.

typedef void * Base; 
typedef char * String;
typedef enum {false, true} Boolean;

.

typedef struct {
  int ra;
  String name;
  } Student;

.

typedef struct AuxNoArv {
  Student info;                   
  struct AuxNoArv *left,*right;  
  } NoArv, * ImplBase;

最佳答案

首先,您将 typedefd Base 设置为 void *,因此 Base *< 类型的函数参数 不是 void * - 它是 void **void * 是通用指针,但 void ** 不是,因此您需要修复它。

其次,您必须在取消引用之前强制转换或以其他方式将 void * 转换为适当的类型,如下所示:

#include <stdio.h>

typedef void * Base; 
typedef char * String;

typedef struct {
    int ra;
    String name;
} Student;

void change_student(Base p)
{
    Student * s = p;
    s->ra = 8;
    s->name = "Legs on a spider";
}

void print_student(Base p)
{
    Student * s = p;
    printf("%d, %s\n", s->ra, s->name);
}

int main(void)
{
    Student my_student = {42, "Meaning of life"};
    print_student(&my_student);
    change_student(&my_student);
    print_student(&my_student);

    return 0;
}

哪些输出:

paul@horus:~/src/sandbox$ ./void
42, Meaning of life
8, Legs on a spider
paul@horus:~/src/sandbox$ 

如果您需要指向指针的指针,例如指向 malloc() 节点的一些内存,如您在评论中所建议的那样,则可以是 Student **转换为 void *Student * 一样好,像这样:

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

typedef void * Base; 
typedef char * String;

typedef struct {
    int ra;
    String name;
} Student;

void change_student(Base p)
{
    Student * s = *((Student **) p);
    if ( s ) {
        s->ra = 8;
        s->name = "Legs on a spider";
    }
    else {
        Student * new_student = malloc(sizeof *new_student);
        if ( !new_student ) {
            perror("couldn't allocate memory");
            exit(EXIT_FAILURE);
        }
        new_student->ra = 4;
        new_student->name = "Horsemen of the Apocalypse";
        *((Student **) p) = new_student;
    }
}

void print_student(Base p)
{
    Student * s = p;
    printf("%d, %s\n", s->ra, s->name);
}

int main(void)
{
    Student my_student = {42, "Meaning of life"};
    Student * pstudent = &my_student;
    print_student(pstudent);
    change_student(&pstudent);
    print_student(pstudent);

    Student * nstudent = NULL;
    change_student(&nstudent);
    print_student(nstudent);

    free(nstudent);

    return 0;
}

产量:

paul@horus:~/src/sandbox$ ./void2
42, Meaning of life
8, Legs on a spider
4, Horsemen of the Apocalypse
paul@horus:~/src/sandbox$ 

关于C:通过空指针引用结构的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26653650/

相关文章:

带 void 和非 void 指针参数的函数指针之间的转换

c - 试图了解 Microchip PIC16LF15344 I2C 外围引脚选择

python - 如何确定二叉树节点是左 child 还是右 child ?

C - 使用后序遍历释放二叉树的内存

c++ - 指针转换/转换解决方案 将 C 升级到 C++

c - 在双链表上查找带有 void * 的函数

c - 论据从右到左阅读

c++ - 是否有调试器可以让我通过代码向后退一步?

c++ - 在 MSVC 中强制未对齐的位域打包

Java BST 递归