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

C:通过空指针引用结构的正确方法,c,binary-search-tree,void-pointers,C,Binary Search Tree,Void Pointers,我正在尝试将Student类型的元素(定义如下)插入到“NoArv”(定义如下)类型结构的字段“info”中。 我需要通过一个o类型的指针“Base”来实现这一点,它是一个空指针 我尝试下面的代码,但在编译时,我收到以下错误消息: > base.c:38:19: error: dereferencing ‘void *’ pointer [-Werror] > if(a.ra < (*p)->info.ra) > ^

我正在尝试将Student类型的元素(定义如下)插入到“NoArv”(定义如下)类型结构的字段“info”中。 我需要通过一个o类型的指针“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;
>
>                 ^


首先,您将
typedef
d
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;
}
#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;
}
如果您需要指向指针的指针,例如指向
malloc()

#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;
}
#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 Griffiths的想法,得到了这个代码。 但这是行不通的。正如格里菲斯在评论中指出的,这只是内存泄漏

Boolean InsertBase(Base *p, Student a) {

  ImplBase s = *p;

  while(s != NULL){
    if(a.ra < s->info.ra)
      s = s->left;
    else if(a.ra > s->info.ra)
      s = s->right;
    else
      return false;
  }

  s = MALLOC(sizeof(NoArv));
  s->info.ra = a.ra;
  s->info.name = a.name;

  s->left = s->right = NULL;

  return true;

}
Boolean InsertBase(Base*p,学生a){
ImplBase s=*p;
while(s!=NULL){
如果(a.rainfo.ra)
s=s->左;
否则如果(a.ra>s->info.ra)
s=s->右;
其他的
返回false;
}
s=MALLOC(sizeof(NoArv));
s->info.ra=a.ra;
s->info.name=a.name;
s->left=s->right=NULL;
返回true;
}

在typedefs后面隐藏指针是导致错误的原因。在取消引用之前,您需要将其转换为适当的类型。无论是否使用typedefs,都不能取消引用
void*
。您必须首先将其转换为另一种指针类型。还有一个问题是,
AuxNoArv
结构中的
info
元素不是指针,因此您不应该分配给它。
((NoArv*)*p)=malloc(sizeof(NoArv))
((NoArv*)*p)->info=MALLOC(sizeof(学生))
要告诉编译器使用
p
指向的
void*
作为指向
NoArv
Paul的指针,您的代码建议将完全删除NoArv结构。p应指向NoArv结构,而不是学生结构。但我明白了大概的意思,而且成功了!谢谢。@Kaiser:是的,这是经过深思熟虑的,我是想回答你的实际问题“通过空指针引用结构的正确方法”,而不是试图实现你正在编写的程序。这只会泄漏内存,你存储在
s
中的地址将在函数结束时被丢弃,因为
s
是一个局部变量。
paul@horus:~/src/sandbox$ ./void
42, Meaning of life
8, Legs on a spider
paul@horus:~/src/sandbox$ 
#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$ 
Boolean InsertBase(Base *p, Student a) {

  ImplBase s = *p;

  while(s != NULL){
    if(a.ra < s->info.ra)
      s = s->left;
    else if(a.ra > s->info.ra)
      s = s->right;
    else
      return false;
  }

  s = MALLOC(sizeof(NoArv));
  s->info.ra = a.ra;
  s->info.name = a.name;

  s->left = s->right = NULL;

  return true;

}