c - 使用 MACROS 进行队列

标签 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;
}

我对这里指针的使用感到非常困惑。我知道指针的工作原理及其背后的理论。但在上述情况下我感到困惑。

最佳答案

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

要声明一个队列,只需:

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/

相关文章:

c - 文件读写问题

c - st_ino st_mode 给出错误的值

c - 寻找有效的交换字符指针

embedded - AUTOSAR 配置 - DCM 模块

可以接受强制门户上的条款的嵌入式 WiFi 设备?

python - 非常简单的代码在c中加载python模块

c - 除以零不会导致 Nvidia Jetson 运行时异常

c - 如何在 C 中正确链接 winsock2.h?

c++ - 如何清除串行屏幕?

embedded - STM32 SPI驱动接收数据一直为0