Linux内核container_of宏和C90中的通用容器

发布于 2024-10-31 07:51:53 字数 625 浏览 5 评论 0 原文

是否可以实现 container_of 纯C90 中的宏?我不确定如何做到这一点,因为内核实现取决于 GCC Hacks,例如 typeof 运算符。

我这样问是因为我想在 C90 中实现一个类似于内核的通用容器 链接列表。我正在考虑的实际容器是一个排序集,类似于您可以从 增强多重索引

Is it possible to implement the container_of macro in pure C90? I'm not sure how to do it as the Kernel implementation depends on GCC Hacks such as the typeof operator.

I'm asking because I would like to implement a generic container in C90 similar to the Kernel's linked list. The actual container I'm thinking of is a sequenced set similar to what you might get from Boost MultiIndex.

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

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

发布评论

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

评论(2

‘画卷フ 2024-11-07 07:51:53

container_of() 的内核定义中使用 typeof 仅用于编译时类型检查 - 它确保传递的 ptr 是实际上是一个指向与member相同类型的指针。可以将其修改为完全 ANSI C,但需要进行类型检查:(

#define container_of(ptr, type, member) ((type *)((char *)ptr - offsetof(type, member)))

offsetof() 位于 中)

The use of typeof in the kernel definition of container_of() is just for compile-time type-checking - it ensures that the passed ptr is really a pointer to the same type as member. It can be modified to be entirely ANSI C at the cost of this type-checking:

#define container_of(ptr, type, member) ((type *)((char *)ptr - offsetof(type, member)))

(offsetof() is in <stddef.h>)

八巷 2024-11-07 07:51:53

是的。
诀窍是替换复合表达式和用于类型检查的typeof。可以通过将 (ptr) 的求值替换为:

(1 ? (ptr) : &((type*)0)->member)

条件运算符始终返回第一个操作数,因为其选择操作数为 1。另一个操作数不求值,因此由于 NULL 解引用而没有 UB。此外,?: 的操作数类型必须兼容,强制编译器进行类型检查。

最终的宏是:

#define container_of(ptr, type, member)          \
  ((type*)((char*)(1 ? (ptr) : &((type*)0)->member) - offsetof(type, member)))

这个宏甚至比原来的container_of更好

C89 变体可以在文件范围内使用或用于静态变量的初始化,而 Linux 则不能。

Yes.
The trick is replacing compound expression and typeof used for type checking. It can be done by replacing evaluation of (ptr) with:

(1 ? (ptr) : &((type*)0)->member)

A conditional operator always returns the first operand because its selection operand is 1. The other operand is not evaluated, therefore there is no UB due to NULL dereferencing. Moreover, the types of operands of ?: have to be compatible forcing type checking from a compiler.

The final macro is:

#define container_of(ptr, type, member)          \
  ((type*)((char*)(1 ? (ptr) : &((type*)0)->member) - offsetof(type, member)))

This macro is even better than the original container_of.

The C89 variant can be used at file scope or for initialization of static variables, while the Linux one cannot.

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