Linux 内核代码中的 C 宏扩展

发布于 2024-08-29 04:32:21 字数 529 浏览 2 评论 0原文

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

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

您可以从 此处。

我不理解LIST_HEAD_INIT中与号的功能(我不认为它们是操作数的地址)以及代码中LIST_HEAD_INIT的使用。如果有人能启发我,我将不胜感激。

I generally have ignored using macros while writing in C but I think I know fundamentals about them. While I was reading the source code of list in linux kernel, I saw something like that:

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

(You can access the remaining part of the code from here.)

I didn't understand the function of ampersands(I don't think they are the address of operands here) in LIST_HEAD_INIT and so the use of LIST_HEAD_INIT in the code. I'd appreciate if someone can enlighten me.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

深陷 2024-09-05 04:32:21

要了解实际发生的情况,我们需要 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;

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

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

编辑:

这是一个工作示例

您提供的链接。你有:

struct list_head test = LIST_HEAD (check);

这是不正确的。你应该有:

LIST_HEAD (check);

To know what actually is happening we need the definition of struct list_head:

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

Now consider the macros:

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

If in the code I write LIST_HEAD(foo) it gets expanded to:

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

which represents an empty doubly linked list with a header node where the next and prev pointers point to the header node itself.

It is same as doing:

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

So effectively these macros provide a way to initialize a doubly linked list.

And yes, & is used here as the address of operator.

EDIT:

Here is a working example

In the link provided by you. You had:

struct list_head test = LIST_HEAD (check);

which is incorrect. You should have:

LIST_HEAD (check);
暮凉 2024-09-05 04:32:21

每当您对宏实际上在做什么有疑问时,您可以要求“gcc -E”为您扩展它。

在这种情况下,它只是用指向自身的指针初始化一个列表结构。

Every time you're in doubt on what macro is actually doing, you can ask 'gcc -E' to expand it for you.

In this case it just initialise a list structure with pointers to itself.

画▽骨i 2024-09-05 04:32:21

他们在这里是地址运算符。内核中的链表避免使用空指针来表示列表的末尾。因此,必须使用一些有效的指针来初始化标头。在此实现中,如果“头”或“尾”指针指向列表头的地址,则该列表被认为是空的。

They are address-of operators here. The linked lists in the kernel avoid null pointers to denote the end of a list. Therefore, the header must be initialized with some valid pointer. In this implementation, if the "head" or "tail" pointer point to the address of the list header, the list is considered empty.

我ぃ本無心為│何有愛 2024-09-05 04:32:21

list.h 中似乎没有使用宏本身。

我假设 & 确实意味着代码中的地址。 struct list_head 包含两个指针,因此声明 struct list_head name = LIST_HEAD_INIT(name) (参见宏 LIST_HEAD)应该很自然获取一对指针作为初始值设定项。

The macro itself seems to be not used in the list.h.

I assume & mean indeed addresses in the code. The struct list_head contains two pointers, so it should be quite natural for declaration struct list_head name = LIST_HEAD_INIT(name) (see macro LIST_HEAD) to obtain a pair of pointers as initializer.

等你爱我 2024-09-05 04:32:21

这正是它们的本质,& 符号获取参数的地址并将它们存储在“head”和“next”列表字段中。无法告诉你为什么,因为我没有找到这个宏的实际用途,但这就是它的作用。

That's exactly what they are, the ampersands take the address of the parameter and store them in both in the "head" and "next" list fields. Couldn't tell you why, since I didn't find an actual use of this macro, but that's what it does.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文