【问题标题】:void Pointer to a structure causes error 'dereferencing 'void *' pointer'void 指向结构的指针导致错误'取消引用'void *'指针'
【发布时间】:2015-01-04 20:07:28
【问题描述】:

我尝试初始化一个名为 initAmigo 的 queueADT 指针。显然,如果结构没有为 (void *data) 制作指针,我永远不会创建一个

我不能将任何数据放入节点结构中的 void *data 的原因:

假设 1:去掉 void *data 并说 User_struct(来自 .h 文件)

假设 2:RegisteredData 不应该是指针,因为 que_Insert 中的参数要求指针)

假设3:在AddUser函数中,que_insert(initAmigo,registeredData); void *data节点中要插入的registeredData实际上是一个指向结构体的指针

队列引用 void * 会产生以下错误:

amigonet.c: In function 'findUser':
amigonet.c:247:21: warning: dereferencing 'void *' pointer [enabled by default]
   if (currNode->data->name == name) {  //If front is the name being searched
                     ^
amigonet.c:247:21: error: request for member 'name' in something not a structure or union
amigonet.c:253:22: warning: dereferencing 'void *' pointer [enabled by default]
    if (currNode->data->name == name ) {

.c 文件只需要创建一个用户队列结构 (QueueADT initAmigo)

typedef struct node {
                                    //name of data userStruct (just for referencing)
    void* data;
    struct node *next;
}node;


struct queueStruct {
    struct node *front;                             /* pointer to front of queue */
    struct node *rear;                              /* pointer to rear of queue  */
    int (*cmprFunc)(const void*a,const void*b);     /* The compare                                          function used for insert */

};

typedef struct queueStruct *QueueADT;       //typedef inserted for pointers, 
                                                //name is QueueADT

#define _QUEUE_IMPL_
#include "queueADT.h"

/// create a queue that is either sorted by cmp or FIFO
//function with two void
QueueADT que_create( int (*cmp)(const void*a,const void*b) ) {

    QueueADT new;
    new = (QueueADT)malloc(sizeof(struct queueStruct));     //NOTE: NO POINTERS HERE
                                                            //use pointers in Single lines
    if (cmp == NULL) {
        new->front = NULL;
        new->rear = NULL;
        new->cmprFunc = NULL;

    } else {
        new->cmprFunc = cmp;
        new->front = NULL;
        new->rear = NULL;
    }
    return ( new );
}

//free the queue once the nodes have been cleared from the queue
void que_destroy( QueueADT queue ) {
    if ( queue->front == NULL ) {
        free(queue);
    } else {
        que_clear(queue);
        free(queue);
    }
}

//passes a real pointer for dynamic allocation
//set a temp to the front to be deleted, then front becomes the next and delete the temp

void que_clear( QueueADT queue ) {


    while (queue->front->next != NULL) {
        struct node *temp;
        temp = (struct node*)malloc(sizeof(struct node));
        temp = queue->front;
        queue->front= queue->front->next;

        free(temp);
        }
}


//if the cmpr function returns a positive then put in in before the b node in cmp(curr, temp)   
void que_insert( QueueADT queue, void *data ) {
    struct node *temp;
    temp = (struct node*)malloc(sizeof(struct node));
    temp->data= data;
    temp->next = NULL;
    node *currNode;             //simply a pointer
    currNode = queue->front;
    if ( queue->front != NULL ) {               //+1 or more in Q
            if ( queue->cmprFunc == NULL ) {        //if the cmp_func is FIFO

                queue->rear->next = temp;
                queue->rear= temp;
                queue->rear->next=NULL;
                if ( queue->front == queue->rear ) {
                    currNode->next = temp;
                    queue->rear = temp;
                    temp->next= NULL;
                    }
            } else {

                while ( currNode->next != NULL ){       //2 or more
                    if (( (*(queue->cmprFunc))(currNode->data, temp->data) >= 0 
                           && ( currNode == queue->front)) ) {
                            temp->next = currNode;
                            queue->front=temp;
                            break;
                            }
                    if (( (*(queue->cmprFunc))(currNode->next->data, temp->data) >= 0 ) ) {             

                            temp->next = currNode->next;
                            currNode->next = temp;
                            break;
                    } else  {
                        currNode = currNode->next;          //move past front and possibly rear
                        if (currNode->next == NULL )  {     //currNode is rear of queue
                            currNode->next = temp;
                            queue->rear = temp;
                            temp->next = NULL;
                            break;
                        }
                                            //exit_failure  
                    }
                }
                if ( queue->front == queue->rear ) {        //exactly 1 node in queue

                    if (( (*(queue->cmprFunc))(currNode->data, temp->data) >= 0 ) ) {

                            temp->next = queue->front;
                            queue->front = temp;
                        } else {

                            queue->front->next = temp;
                            queue->rear = temp;

                        }
                    }
            }
    } else {                                            
        queue->front = temp;
        queue->rear= queue->front;
        queue->front->next= queue->rear->next = NULL;

        }
    }


//removes the front
void *que_remove( QueueADT queue ) {
    if ( queue->front != NULL ) {       //if the size of queue is greater than 1
        node *currNode;                 // dont make new node, pointer
        currNode = queue->front;
        void *data = currNode->data;
        if ( queue->front == queue->rear ) { //if size of queue is 1
            free(currNode);
            queue->front = queue->rear = NULL; //set both to NULL
        } else {
            queue->front= currNode->next;
            free(currNode);
        }
        return data;    
    }
    return NULL;
}

bool que_empty( QueueADT queue ) {
    if ( queue->front == NULL ) {
        return true;
    } else {
        return false;
        }
}


QueueADT initAmigo; 

//struct queueStruct *initAmigo
//QueueADT initAmigo;

//make a Queue with front and rear
    //compare function with A-Z

struct Friends_struct {
    struct queueStruct *amigos_Queue;
};  


void create_amigonet() {
    //makes the same thing as que_Create 
    //(Friends)malloc(sizeof(struct Friend_struct));

    initAmigo = que_create(NULL);
    printf("%lu Founded size of an.c\n\n\n\n\n\n\n\n\n\n\n", sizeof(initAmigo));
}


//The add user will find a new user and make the name of the user to a amigonet
//add Usernode to queue initAmigo
//make sure set to first and display queue

void addUser( const char *name ) {
    //create Usernode and void *data (user w/ friends)
    //check to see if User already exists
    if ( findUser(name) != NULL) {
        return;
    }
    //create data for node, by initializing memorry for a userStruct
    struct User_struct *registeredData;
    registeredData = ( struct User_struct* )malloc(sizeof(struct User_struct));     //first user Data

    registeredData->name = name;

    //create a Friends
        //put this in file create F
    struct Friends_struct *initAmigos;
    initAmigos = (struct Friends_struct*)malloc(sizeof(struct Friends_struct));     //NOTE: NO POINTERS HERE
    //set Friends list to Null
    initAmigos->amigos_Queue = que_create( NULL );

    //put User with empty Friends struct
    registeredData->amigos = initAmigos;

    //void que_insert( QueueADT queue, void *data )
    que_insert( initAmigo , registeredData);
    printf("%s User was inerted \n", name);

}
//Find a user in the init Amgio
//start at front as temp, go to next until name found

User *findUser( const char *name ) {
    struct node *currNode;
    currNode =  initAmigo->front;
    printf("%lu Founded size of an.c\n\n\n\n\n\n\n\n\n\n\n", sizeof(initAmigo));
    if ( initAmigo->front == NULL ) {
        return NULL;
    } else {
        if (currNode->data->name == name) {  //If front is the name being searched
            return currNode->data;
        }
               //Loop after front 
        while ( currNode->next != NULL ) {
            currNode = currNode->next;
            if (currNode->data->name == name ) {
                return currNode->data;
            }
        }
        node *rear = currNode;
        if (rear->data->name == name ) {
            return rear->data;
        }
    }
    //User Not Founded
    return; 
}
#if 0
void addAmigo( User *user, User *amigo ) {

    //check to see if node exits within friends
    //go to use friends list
    //traverse the node, check data for amigo->name == data->name

    if (  user->amigos->amigos_Queue->front != NULL ) {
        node *currNode = user->amigos->amigos_Queue->front;
        if ( currNode->data->name == amigo->name ) {
            return ;
        } else {
            //loop to determine if User friend  queue front to rear has amigo already
            while ( currNode->next != NULL ) {
                currNode = currNode->next;
                if (currNode ->data->name == amigo->name) {
                    return;
                }
            }
        }
    }
    que_insert( user->amigos->amigos_Queue, amigo);
}


void removeAmigo( User *user, User *ex_amigo) {
    //Pre Condition: Amgio exists in user


    //go to user
    //set user as currNode


    //either create a function in queueADT remove
    // use a prev and curr and next and traverse, remove, connect
    //preconditions: front is not examigo
    //   rear is not examigo
    // amigo is friend of user

}


size_t separation( const User *user1, const User *user2 ) {

    return;
    //queue a DFS
    // queue a BFS
    //  
}
//search using a queue BFS
//search using a DFS

//number of users and their names
void dump_data() {
    if (initAmigo->front != NULL) {
        node *currNode = initAmigo->front;
        printf("%s: Amigos!\n", currNode->data->name);      //prints the name of the first node
        while ( currNode->next != NULL ) {
            currNode = currNode->next;
            printf("%s: Amigos!\n", currNode->data->name);
        }
    //while loop of each user set to currNodw

    //set a variable for currNodeAmigo and print the names of them inside ^^^
    }
}

void destroy_amigonet(){
    //clear Friend Queue and destroy for each User Friend
    //destroy initAmigo queue
}

【问题讨论】:

  • 问题是什么?
  • 问题如下:为什么在que_Insert中我放了一个User_struct的结构时,它说我在取消引用一个void *data?如何插入没有错误的结构?当我没有使用 ->data->name 转换指针时,在 FindUser 中初始化 void *Data 时,AddUser 有问题吗?

标签: c pointers struct void-pointers abstract-data-type


【解决方案1】:

问题如下:

typedef struct node {
  void* data;
  struct node *next;
}node;

...

struct node *currNode;

if (currNode->data->name == name) {  //If front is the name being searched
    return currNode->data;
}

currNode->data 的类型是void *。这是一个不完整的类型,这意味着它不能被取消引用。编译器不知道如何处理它指向的任何内容。您需要将 void 指针 转换 为指向有意义类型的指针。

您尚未在发布的代码中定义 User 类型,但我猜您想要这样的东西:

User *user = currNode->data;

if (user->name == name) {
    return user;
}

您还必须在同一函数的其他地方进行类似的更改。

【讨论】:

  • 我真的很喜欢 void *data,但是它用于我的上一个项目,我实际上可以将其更改为结构的真实名称并使用它更改所有参数。你会真正工作还是会创建另一个指向指针的指针?
  • 用户在h文件中定义为typedef struct User_struct {const char *name;Friends amigos;} User;AddUser函数改变了void *data指向那个结构,所以我是这么想的。
  • @arrowinfedex:如果您希望que 函数具有通用性(能够处理任何类型的对象),那么您需要 void *data 成员。如果您只关心一种类型的对象,那么始终使用正确的类型将提供更好的类型安全性。这是你的电话。
  • 我和我的朋友谈过,他说得更具体,说我需要为 void *data 转换参数。假设我可以使用 createAmigo(),addUser 将需要 que_Insert(queue, (*User_struct)registeredData) 听起来对吗?
  • 没有。你所拥有的不是演员表。你的意思是(struct User_struct *)registeredData?然后,再次没有,因为registeredData 已经 具有该类型。将一种类型转换为完全相同的类型有什么意义?您可以传递未转换的值,但是当您再次从队列中检索指针时,请确保将其存储在正确类型的变量中 (struct User_struct *)。不需要演员表。 (无论如何,在 C 中。C++ 有不同的规则)。
猜你喜欢
  • 2016-03-21
  • 1970-01-01
  • 2012-03-25
  • 2014-10-01
  • 2011-10-20
  • 2021-07-19
  • 1970-01-01
  • 1970-01-01
  • 2014-05-30
相关资源
最近更新 更多