I'm trying to insert an element of type Student (definition below) into the field "info" of an structure of type "NoArv" (definition below). I NEED to do this through a pointer o type "Base", which is a void-pointer.
我试图将Student类型的元素(定义如下)插入到NoArv类型结构的“info”字段中(定义如下)。我需要通过一个指针o类型的“Base”来实现这一点,它是一个void指针。
I try the code below, but when compiling, I receive the following error message:
我尝试下面的代码,但是在编译时,我收到以下错误消息:
> 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;
>
> ^
How can I correctly dereference such a pointer to a void type?
如何正确地取消对void类型的指针的引用?
I call the function with this: InsereBase(&base, student)
我用这个函数调用这个函数:InsereBase(&base,学生)
Where "base" is a variable of type Base and "student" is an element of type Student.
“base”是类型基础的变量,“student”是类型student的一个元素。
CODE:
代码:
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;
2 个解决方案
#1
2
First of all, you've typedef
d Base
as void *
, so a function argument of type Base *
is not a void *
- it's a void **
. void *
is a generic pointer, but void **
is not, so you'll want to fix that.
首先,您将typedefd基设为void *,所以Base *类型的函数参数不是void *——而是void *。void *是一个通用指针,而void *不是,所以您需要修复它。
Second, you have to cast or otherwise convert a void *
to the appropriate type before dereferencing it, like so:
第二,在取消引用之前,您必须将一个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;
}
which outputs:
输出:
paul@horus:~/src/sandbox$ ./void
42, Meaning of life
8, Legs on a spider
paul@horus:~/src/sandbox$
If you need pointers to pointers, for instance to malloc()
some memory for a node as you suggest in your comments, then something like Student **
can be converted to void *
just as well as Student *
can, like so:
如果您需要指向指针的指针,例如指向malloc()的指针,如您在注释中建议的某个节点的内存,则可以将Student **之类的内容转换为void *,就像Student *可以转换为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;
}
yielding:
收益率:
paul@horus:~/src/sandbox$ ./void2
42, Meaning of life
8, Legs on a spider
4, Horsemen of the Apocalypse
paul@horus:~/src/sandbox$
#2
0
I used Paul Griffiths idea and get this code. But that is NOT working. As Griffiths noted in comments, it is just leaking memory.
我用了保罗·格里菲思的想法,得到了这个代码。但这是行不通的。正如格里菲斯在评论中指出的那样,这只是内存泄漏。
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;
}
#1
2
First of all, you've typedef
d Base
as void *
, so a function argument of type Base *
is not a void *
- it's a void **
. void *
is a generic pointer, but void **
is not, so you'll want to fix that.
首先,您将typedefd基设为void *,所以Base *类型的函数参数不是void *——而是void *。void *是一个通用指针,而void *不是,所以您需要修复它。
Second, you have to cast or otherwise convert a void *
to the appropriate type before dereferencing it, like so:
第二,在取消引用之前,您必须将一个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;
}
which outputs:
输出:
paul@horus:~/src/sandbox$ ./void
42, Meaning of life
8, Legs on a spider
paul@horus:~/src/sandbox$
If you need pointers to pointers, for instance to malloc()
some memory for a node as you suggest in your comments, then something like Student **
can be converted to void *
just as well as Student *
can, like so:
如果您需要指向指针的指针,例如指向malloc()的指针,如您在注释中建议的某个节点的内存,则可以将Student **之类的内容转换为void *,就像Student *可以转换为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;
}
yielding:
收益率:
paul@horus:~/src/sandbox$ ./void2
42, Meaning of life
8, Legs on a spider
4, Horsemen of the Apocalypse
paul@horus:~/src/sandbox$
#2
0
I used Paul Griffiths idea and get this code. But that is NOT working. As Griffiths noted in comments, it is just leaking memory.
我用了保罗·格里菲思的想法,得到了这个代码。但这是行不通的。正如格里菲斯在评论中指出的那样,这只是内存泄漏。
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;
}