无法访问铸造的虚空指针
Unable to Access Casted Void Pointer
我正在创建一个链表,其中包含带有 "dataItem" 空指针的节点。这样做的目的是为了让节点能够包含任何类型的数据。但是,我无法访问 void 指针的数据,即使该数据已转换为正确的类型。
我的代码如下所示:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Student
{
char stuName[51];
char stuMajor[5];
double GPA;
char stuID[10];
}student;
typedef struct Node
{
union{
void *dataPtr;
int countr;
}dataItem;
int link;
struct Node* next;
}node;
void readData(struct Node *);
void main(){
node head;
node temp;
readData(&temp);
student *ptr = (student *)(temp.dataItem.dataPtr);
printf("%s %d", ptr->stuName, ptr->GPA);//breaks here because unable to access memory
}
void readData(struct Node *link)
{
link = (node *)malloc(sizeof(node));
student *ptr = (student *)malloc(sizeof(struct Student));
printf("enter the student name : ");
fflush(stdin);
scanf("%[^\n]", ptr->stuName);
printf("enter the student's major : ");
fflush(stdin);
scanf("%[^\n]", ptr->stuMajor);
printf("enter the student GPA : ");
scanf("%lf", &(ptr->GPA));
printf("enter the student ID : ");
fflush(stdin);
scanf("%[^\n]", ptr->stuID);
link->dataItem.dataPtr = ptr;
}
我知道我肯定在某个地方有一个指针错误我不确定如何。我的 readData
函数中的节点也指向一个新的 Node malloc,因为在我进一步实现链表时每次调用 readData
时我都想要一个新节点。
你的代码很糟糕,
您没有包含任何头文件,malloc()
至少需要 stdlib.h
,printf()
和 [= 至少需要 stdio.h
15=].
你的main()
定义是错误的,因为main()
必须returnint
.
你fflush(stdin)
这是未定义的行为。
您忽略 scanf()
中的 return 值。
您假设 malloc()
总是 return 是一个有效的指针。
您调用了尚未声明的 readData()
。
但最重要的错误是,您将 node temp
的地址传递给 readData()
并 malloc()
编辑了它,但您没有 return指向它的指针,从而丢失在 readData()
中所做的所有更改,这无论如何都不会起作用,因为它在您调用它时未声明。
我修复了你的代码,因为我知道你不喜欢我的答案,但是检查了与答案相关的修复,现在它按我的预期工作了
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Student
{
char stuName[51];
char stuMajor[5];
double GPA;
char stuID[10];
} student;
typedef struct Node
{
union{
void *dataPtr;
int countr;
} dataItem;
int link;
struct Node* next;
} node;
void readData(struct Node **link);
int main()
{
node *head;
student *ptr;
readData(&head);
ptr = head->dataItem.dataPtr;
if (ptr != NULL)
printf("%s\t%g", ptr->stuName, ptr->GPA);
return 0;
}
void readData(struct Node **link)
{
student *ptr;
if (link == NULL)
return;
*link = malloc(sizeof(node));
if (*link == NULL)
return;
memset(*link, 0, sizeof(node));
ptr = malloc(sizeof(struct Student));
if (ptr == NULL)
return;
printf("enter the student name : ");
if (scanf("%50[^\n]%*c", ptr->stuName) != 1)
ptr->stuName[0] = '[=10=]';
printf("enter the student's major : ");
if (scanf("%4[^\n]%*c", ptr->stuMajor) != 1)
ptr->stuMajor[0] = '[=10=]';
printf("enter the student GPA : ");
if (scanf("%lf%*c", &(ptr->GPA)) != 1)
ptr->GPA = 0;
printf("enter the student ID : ");
if (scanf("%9[^\n]%*c", ptr->stuID) != 1)
ptr->stuID[0] = 0;
(*link)->dataItem.dataPtr = ptr;
}
我还对 scanf()
添加了一些安全修复程序,添加了长度修饰符以防止缓冲区溢出,并且还删除了带有 "%*c"
说明符的尾随 '\n'
,如果多个,它将不起作用空格跟在值后面,但是你可以同时按下 Enter/Return 来测试它,如果你想要更复杂的输入,你应该使用其他东西而不是 scanf()
.
这个:
void readData(struct Node *link)
{
link = (node *)malloc(sizeof(node));
您丢弃了传入的 link
参数值,而是通过 malloc
为其分配新的分配。我认为这是你最重要的问题。一个简单的修复方法是删除执行 malloc
.
的行
您想将一个指向一个节点的指针(或指针的地址)的指针传递给 readData() 函数。 readData 分配一个新节点并填充它;在你的代码中发生的事情是 readData() 得到一个 copy 的临时地址,用一个新地址覆盖这个地址的副本,这个地址是从 malloc 获得的(这是不可见的) main()) 中的调用代码,然后填充该 malloc 对象。在 return 从 readData 中,无法访问 malloc 对象。
你想做的是:
void main(){
node head;
node *tempAddr; // pointer
readData(&tempAddr); // pass address of that pointer
然后在 main 中使用 *tempAddr
而不是 temp
。
void readData(struct Node **linkAddr)
{
node *link = *linkAddr = (node *)malloc(sizeof(node));
[...]
unwind 会抱怨你不应该转换 malloc 的结果,但我认为这很好。我也不关心 main 的 return 值或其参数。
我正在创建一个链表,其中包含带有 "dataItem" 空指针的节点。这样做的目的是为了让节点能够包含任何类型的数据。但是,我无法访问 void 指针的数据,即使该数据已转换为正确的类型。
我的代码如下所示:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Student
{
char stuName[51];
char stuMajor[5];
double GPA;
char stuID[10];
}student;
typedef struct Node
{
union{
void *dataPtr;
int countr;
}dataItem;
int link;
struct Node* next;
}node;
void readData(struct Node *);
void main(){
node head;
node temp;
readData(&temp);
student *ptr = (student *)(temp.dataItem.dataPtr);
printf("%s %d", ptr->stuName, ptr->GPA);//breaks here because unable to access memory
}
void readData(struct Node *link)
{
link = (node *)malloc(sizeof(node));
student *ptr = (student *)malloc(sizeof(struct Student));
printf("enter the student name : ");
fflush(stdin);
scanf("%[^\n]", ptr->stuName);
printf("enter the student's major : ");
fflush(stdin);
scanf("%[^\n]", ptr->stuMajor);
printf("enter the student GPA : ");
scanf("%lf", &(ptr->GPA));
printf("enter the student ID : ");
fflush(stdin);
scanf("%[^\n]", ptr->stuID);
link->dataItem.dataPtr = ptr;
}
我知道我肯定在某个地方有一个指针错误我不确定如何。我的 readData
函数中的节点也指向一个新的 Node malloc,因为在我进一步实现链表时每次调用 readData
时我都想要一个新节点。
你的代码很糟糕,
您没有包含任何头文件,
malloc()
至少需要stdlib.h
,printf()
和 [= 至少需要stdio.h
15=].你的
main()
定义是错误的,因为main()
必须returnint
.你
fflush(stdin)
这是未定义的行为。您忽略
scanf()
中的 return 值。您假设
malloc()
总是 return 是一个有效的指针。您调用了尚未声明的
readData()
。
但最重要的错误是,您将 node temp
的地址传递给 readData()
并 malloc()
编辑了它,但您没有 return指向它的指针,从而丢失在 readData()
中所做的所有更改,这无论如何都不会起作用,因为它在您调用它时未声明。
我修复了你的代码,因为我知道你不喜欢我的答案,但是检查了与答案相关的修复,现在它按我的预期工作了
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Student
{
char stuName[51];
char stuMajor[5];
double GPA;
char stuID[10];
} student;
typedef struct Node
{
union{
void *dataPtr;
int countr;
} dataItem;
int link;
struct Node* next;
} node;
void readData(struct Node **link);
int main()
{
node *head;
student *ptr;
readData(&head);
ptr = head->dataItem.dataPtr;
if (ptr != NULL)
printf("%s\t%g", ptr->stuName, ptr->GPA);
return 0;
}
void readData(struct Node **link)
{
student *ptr;
if (link == NULL)
return;
*link = malloc(sizeof(node));
if (*link == NULL)
return;
memset(*link, 0, sizeof(node));
ptr = malloc(sizeof(struct Student));
if (ptr == NULL)
return;
printf("enter the student name : ");
if (scanf("%50[^\n]%*c", ptr->stuName) != 1)
ptr->stuName[0] = '[=10=]';
printf("enter the student's major : ");
if (scanf("%4[^\n]%*c", ptr->stuMajor) != 1)
ptr->stuMajor[0] = '[=10=]';
printf("enter the student GPA : ");
if (scanf("%lf%*c", &(ptr->GPA)) != 1)
ptr->GPA = 0;
printf("enter the student ID : ");
if (scanf("%9[^\n]%*c", ptr->stuID) != 1)
ptr->stuID[0] = 0;
(*link)->dataItem.dataPtr = ptr;
}
我还对 scanf()
添加了一些安全修复程序,添加了长度修饰符以防止缓冲区溢出,并且还删除了带有 "%*c"
说明符的尾随 '\n'
,如果多个,它将不起作用空格跟在值后面,但是你可以同时按下 Enter/Return 来测试它,如果你想要更复杂的输入,你应该使用其他东西而不是 scanf()
.
这个:
void readData(struct Node *link)
{
link = (node *)malloc(sizeof(node));
您丢弃了传入的 link
参数值,而是通过 malloc
为其分配新的分配。我认为这是你最重要的问题。一个简单的修复方法是删除执行 malloc
.
您想将一个指向一个节点的指针(或指针的地址)的指针传递给 readData() 函数。 readData 分配一个新节点并填充它;在你的代码中发生的事情是 readData() 得到一个 copy 的临时地址,用一个新地址覆盖这个地址的副本,这个地址是从 malloc 获得的(这是不可见的) main()) 中的调用代码,然后填充该 malloc 对象。在 return 从 readData 中,无法访问 malloc 对象。
你想做的是:
void main(){
node head;
node *tempAddr; // pointer
readData(&tempAddr); // pass address of that pointer
然后在 main 中使用 *tempAddr
而不是 temp
。
void readData(struct Node **linkAddr)
{
node *link = *linkAddr = (node *)malloc(sizeof(node));
[...]
unwind 会抱怨你不应该转换 malloc 的结果,但我认为这很好。我也不关心 main 的 return 值或其参数。