C:通过空指针引用结构的正确方法
我正在尝试将Student类型的元素(定义如下)插入到“NoArv”(定义如下)类型结构的字段“info”中。 我需要通过一个o类型的指针“Base”来实现这一点,它是一个空指针 我尝试下面的代码,但在编译时,我收到以下错误消息: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) > ^
> 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
dBase
设置为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;
}