【问题标题】:C Issues with pointers and a queueC 指针和队列问题
【发布时间】:2014-06-23 11:17:14
【问题描述】:

我使用的是一个自写的队列库,结构如下:

#ifndef MYQUEUE_
#define MYQUEUE_

#ifndef SET_QUEUE_SIZE
    #define SET_QUEUE_SIZE 10
#endif

typedef struct queue Queue;

/*
**  Creates and initializes the queue and prepares it for usage
**  Return a pointer to the newly created queue
*/
Queue* QueueCreate();

/*  
**  Add an element of a generic type to the queue
*/
void Enqueue(Queue* queue, void* element);

/*
**  Delete the queue from memory; set queue to NULL
**  The queue can no longer be used unless QueueCreate is called again
*/
void QueueDestroy(Queue** queue);


/*
**  Return the number of elements in the queue
*/
int QueueSize(Queue* queue);

/*
**  Return a pointer to the top element in the queue
*/
void* QueueTop(Queue* queue);

/*
**  Remove the top element from the queue
*/
void Dequeue(Queue* queue);


#endif //MYQUEUE_

现在,我在将其放入和从循环队列中取出时遇到了问题。队列本身已经过测试,应该没有任何问题。

运行下面的代码(它是整个程序的摘录)我的两个打印不打印相同的值。我哪里错了?

#include <stdlib.h>
#include <stdio.h>
#include <time.h>

#include "libs/myqueue.h"

struct package{
    unsigned sensorId:12;
    unsigned sequence:4;
    unsigned flag:2;
    unsigned sign:1;
    unsigned value:12;
    unsigned parity:1;
};

typedef struct package packs;

struct sensor_time{
    packs myPack;
    time_t time;
};

typedef struct sensor_time Sensor_Time;

Queue* queue = NULL;

int main(void){
    queue = QueueCreate();
    if(queue == NULL){
        printf("Error creating circular buffer.\n");
        exit(EXIT_FAILURE);
    }

    Sensor_Time * myData = malloc(sizeof(Sensor_Time));
    myData->myPack.sensorId = 1;
    myData->myPack.value = 20;
    myData->time = time(NULL);
    printf("Enqueued: id: %d, value: %d, time: %lu\n", myData->myPack.sensorId, myData->myPack.value, myData->time);

    Enqueue(queue, (void *)myData);

    Sensor_Time * mySens = (Sensor_Time *)QueueTop(queue);
    printf("Data read: id: %d, value: %d time: %lu", mySens->myPack.sensorId, mySens->myPack.value, mySens->time);

    return 1;
}

打印的内容:

为了完整起见,这里是队列实现:

/*----- Include Files -----*/

#include <stdlib.h>
#include <stdio.h>

#include "myqueue.h"

/*-----   Variables   -----*/

typedef void * DATATYPE;

struct queue{
    DATATYPE elements[SET_QUEUE_SIZE];
    size_t count;
    int front;
    int rear;
};
typedef struct queue Queue;
typedef Queue *myQueue;

/*----- QueueCreate   -----*/

Queue* QueueCreate(void){
    #ifdef DEBUG
        printf("QueueCreate called.\n");
    #endif

    Queue* qu = malloc(sizeof(Queue));
    qu->count = 0;
    qu->front = 0;
    qu->rear = 0;
    return qu;
}

/*----- QueueCreate    -----*/

void Enqueue(Queue* queue, DATATYPE element){
    #ifdef DEBUG
        printf("Enqueue called,  on queue %p.", queue);
        int location = queue->rear;
    #endif

    if(queue->count == SET_QUEUE_SIZE){
        printf("Queue is full.\n");
    }else{
        queue->elements[queue->rear] = element;
        queue->count++;
        queue->rear++;
        if(queue->rear == SET_QUEUE_SIZE - 1){
            queue->rear = 0;
        }
    }

    #ifdef DEBUG
        printf(" Element added on location %d.\n", location);
    #endif
}

/*----- QueueDestroy   -----*/

void QueueDestroy(Queue** queue){
    #ifdef DEBUG
        printf("QueueDestroy called on %p\n", queue);
    #endif

    free(*queue);
    *queue = NULL;
}

/*----- QueueSize   -----*/

int QueueSize(Queue* queue){
    #ifdef DEBUG
        if(queue->count > 0){
            printf("QueueSize called. Size is %d.\n", (int)queue->count);
        }
    #endif

    return queue->count;
}

/*----- QueueTop    -----*/

void* QueueTop(Queue* queue){
    #ifdef DEBUG
        printf("QueueTop called\n");
    #endif
    if(queue->count == 0){
        return NULL;
    }else{
        return &(queue->elements[queue->front]);
    }
    return NULL;
}

/*----- Dequeue     -----*/

void Dequeue(Queue* queue){
    #ifdef DEBUG
        printf("Dequeue called on %p.", queue);
        int location = queue->front;
    #endif

    if(queue->count == 0){
        printf("Queue is empty.\n");
    }else{
        queue->front++;
        if(queue->front == SET_QUEUE_SIZE - 1){
            queue->front = 0;
        }
        queue->count--;
    }

    #ifdef DEBUG
        printf(" Removed element was on location %d.\n", location);
    #endif
}

【问题讨论】:

  • 我猜它是在 q 实现中......顺便说一句:除非您更改#pragma pack,否则在大多数编译器上使用位域不会为您带来任何空间优势
  • @MarioTheSpoon:它用于分配,通常还有一个带有 unsigned int 的位域的联合,以通过 tcp 套接字发送它。另外,添加了队列实现(它已经针对 int 进行了测试并且可以正常工作,所以我很困惑)
  • 只需更改 return &(queue->elements[queue->front]);返回 queue->elements[queue->front];

标签: c pointers queue


【解决方案1】:

您的队列存储void* 类型的元素。然而,QueueTop 返回一个指向第一个元素的指针,这将使它成为void** 类型。函数被声明为返回 void* 而不是 DATATYPE* 的事实让人感到困惑,但这是合法的,因为任何指针都可以转换为 void*,包括双指针。

将元素添加到队列时,会将其从 Sensor_Time * 转换为 void*。后来在调用QueueTop的时候,你把返回值转换成Sensor_Time *,这是错误的,因为它实际上是一个指向指针的指针。

要解决此问题,您需要更改 QueueTop 以返回元素而不是指向元素的指针,或者更改调用代码以取消引用返回的指针。

【讨论】:

  • 由于提供了myqueue.h 文件,我猜我需要更改我必须取消引用返回的指针的代码。但我似乎遇到了一些问题。目前我做Sensor_Time * mySens = (Sensor_Time *)QueueTop(queue);,但是当像这样取消引用QueueTop时:Sensor_Time * mySens = *(Sensor_Time *)QueueTop(queue);我得到一个不兼容的类型。
  • @arbitter 它是一个双指针,所以在解除引用之前转换为Sensor_Time **
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-16
  • 2023-04-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多