使用MACROS进行队列化

时间:2013-12-20 07:01:38

标签: c embedded

我目前正在开发一个ZigBee WSNDemo项目,我仍然坚持使用这部分代码。基本上,我必须在appInitMsgSender函数中将此宏用于队列目的。

void appInitMsgSender(void)
{
    txState = APP_MSG_TX_FREE_STATE;

    resetQueue(&appToSendQueue);
    resetQueue(&appFreeQueue);
    resetQueue(&appSentQueue);
    resetQueue(&appDoneQueue);

    for (uint8_t i = 0; i < ARRAY_SIZE(appTxBuffers); i++)
    {
        putQueueElem(&appFreeQueue, &appTxBuffers[i].next);
    }
}

以上是应用程序的消息发送初始化函数。以下是用于它的宏。我想知道两者是如何联系的。我的意思是如何理解这段代码的工作原理。

#define DECLARE_QUEUE(queue) QueueDescriptor_t queue = {.head = NULL,}

// Type of queue element
typedef struct _QueueElement_t
{
    struct _QueueElement_t *next;
} QueueElement_t;

// Queue descriptor
typedef struct
{
    QueueElement_t *head;
} QueueDescriptor_t;

INLINE void resetQueue(QueueDescriptor_t *queue)
{
    queue->head = NULL;
}

我真的很困惑这里使用指针。我知道指针的工作原理和理论背后的原理。但在上述背景下,我感到很困惑。

2 个答案:

答案 0 :(得分:3)

这里发生的事情是很多抽象。基本上隐藏细节,使代码的主体更具可读性。当然,你需要在头脑中隐含地理解所有潜在的细节,以便你正在阅读的内容有任何意义。

要声明队列,只需:

DECLARE_QUEUE(appFreeQueue);

如果我们扩展宏,这与写作相同:

QueueDescriptor_t appFreeQueue = {.head = NULL,};

如果我们然后展开QueueDescriptor_t typedef,它将与写作相同:

struct appFreeQueue
{
    QueueElement_t *head = NULL;
};

如果我们扩展QueueElement_t typedef,我们可以看到每个元素都指向同一类型的另一个元素:

struct appFreeQueue
{
    typedef struct _QueueElement_t
    {
        struct _QueueElement_t *next = NULL;
    } *head;
};

但是,不是每次想要声明队列时都写出来,而是可以使用DECLARE_QUEUE宏。这将以链表的形式创建一个空队列。链表通常采用每个链接的形式,包含两个东西,一些数据和指向下一个链接的指针。像这样:

   Element1             Element2             Element3
[data][*Element2]->  [data][*Element3]->  [data][NULL]

这样做的好处在于,您不必在启动时阻止一段内存,并将其保留为空并且未使用,直到需要它就像使用数组一样。相反,每个链接都可以在需要时动态分配,并指向它在前一个链接的内存中的位置。

INLINE函数的行为与宏非常相似。无论你在哪里看到resetQueue,你都应该用你在那里定义的函数替换它。在这种情况下,它将第一个链接的next指针设置为NULL,从而导致空队列。

宏和INLINE功能之间存在细微差别。这个问题的答案中详细描述了这些差异:Inline functions vs Preprocessor macros

答案 1 :(得分:0)

队列使用称为linked list的数据结构实现。 QueueDescriptor_t包含指向列表中第一个QueueElement_t的指针。每个QueueElement_t都包含指向列表中下一个QueueElement_t的指针。当QueueDescriptor_t指针为NULL时,列表为空。当QueueElement_t指针为NULL时,它是列表中的最后一项。链接列表允许您创建项目集合,但项目不必在内存中连续(next指针链接到集合中的下一个项目)。为了进行比较,数组是 在内存中连续的项的集合(不需要next指针)。