我目前正在开发一个 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;
}
我对这里指针的使用感到非常困惑。我知道指针的工作原理及其背后的理论。但在上述情况下我感到困惑。
最佳答案
这里发生的是很多抽象。基本上隐藏细节以使代码主体更具可读性。当然,您需要理解头脑中隐含的所有潜在细节,才能使您所阅读的内容有意义。
要声明一个队列,只需:
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
关于c - 使用 MACROS 进行队列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20698077/