Linux 内核代码中的 C 宏扩展

标签 c linux list macros c-preprocessor

在用 C 编写代码时,我通常会忽略使用宏,但我认为我了解它们的基础知识。当我阅读 linux 内核中 list 的源代码时,我看到了这样的东西:

#define LIST_HEAD_INIT(name) { &(name), &(name) }
#define LIST_HEAD(name) \
    struct list_head name = LIST_HEAD_INIT(name)

(您可以从 here. 访问代码的剩余部分)

我不理解 LIST_HEAD_INIT 中 & 符号的功能(我不认为它们是这里操作数的地址),因此在代码中使用 LIST_HEAD_INIT。如果有人能启发我,我将不胜感激。

最佳答案

要知道实际发生了什么,我们需要定义 struct list_head:

struct list_head {
        struct list_head *next, *prev;
};

现在考虑宏:

#define LIST_HEAD_INIT(name) { &(name), &(name) }
#define LIST_HEAD(name) struct list_head name = LIST_HEAD_INIT(name)

如果在我编写的代码中 LIST_HEAD(foo) 它会扩展为:

struct list_head foo = { &(foo) , &(foo)}

表示一个带有头节点的空双向链表,其中nextprev 指针指向头节点本身。

这等同于:

struct list_head foo;
foo.next = &foo;
foo.prev = &foo;

这些宏非常有效地提供了一种初始化双向链表的方法。

是的,& 在这里用作运算符的地址。

编辑:

这是一个working example

在您提供的链接中。你有:

struct list_head test = LIST_HEAD (check);

这是不正确的。你应该:

LIST_HEAD (check);

关于Linux 内核代码中的 C 宏扩展,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2673728/

相关文章:

c - 如何在 Linux 中调试 FUSE 文件系统崩溃

c - 什么是有符号字符?

c - 数组函数只返回第一个元素,我需要整个数组。请帮助

c++ - 无法理解 "list<int>::iterator i;"

c - 如何在 C 中打印数组元素的摘要

linux - .emacs 文件中的颜色主题设置不正确

linux - 如何在Linux中运行命令限制特定目录中的文件访问?

c# - 字典 OrderBy Issue

java - 迭代器可以从列表中删除不等于特定值的项目吗?

python - 从列表中获取键和值