无法访问Casted Void指针

时间:2015-04-21 15:13:09

标签: c pointers linked-list

我正在创建一个链表,其中包含带有void指针的“dataItem”的节点。这样做的目的是为了使Node能够包含任何类型的数据。但是,即使将数据转换为正确的类型,我也无法访问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时我想要一个新节点。

3 个答案:

答案 0 :(得分:5)

你的代码非常破碎,

  1. 您没有包含任何头文件,stdlib.h至少malloc()stdio.h和{{1}需要printf() }。

  2. 您的scanf()定义错误,因为main()必须返回main()

  3. int是未定义的行为。

  4. 您忽略fflush(stdin)的返回值。

  5. 您认为scanf()始终返回有效指针。

  6. 您调用了尚未声明的malloc()

  7. 但最重要的错误是,您将readData()的地址传递给了node temp并且您readData()编了它,但您没有返回指针它失去了在malloc()内所做的所有变化,但这些变化无论如何都不会起作用,因为它在你调用它的那一刻都没有声明。

    我修改了你的代码,因为我知道你不喜欢我的答案,但查看与答案相关的修复程序,现在它按预期工作

    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] = '\0'; printf("enter the student's major : "); if (scanf("%4[^\n]%*c", ptr->stuMajor) != 1) ptr->stuMajor[0] = '\0'; 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()说明符的尾随'\n',如果跟随多个空格,它将无效值,但你可以测试它,只需按 Enter / Return ,如果你想要更加软化的输入,你应该使用别的而不是"%*c"

答案 1 :(得分:2)

此:

void readData(struct Node *link)
{
    link = (node *)malloc(sizeof(node));

您丢弃传入的link参数值,而是通过malloc为其分配新的分配。我认为这是你最重要的问题。一个简单的解决方法是删除执行malloc的行。

答案 2 :(得分:0)

您希望将指针传递给指向(或指针的地址)指向readData()函数的节点。 readData分配一个新节点并填充它;你的代码中发生的事情是readData()获取temp地址的副本,用新地址覆盖该地址的副本,该地址是从malloc获得的(对于调用代码是不可见的)在main()中然后填充malloc的对象。从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或其参数的返回值。