我一直在寻找一个类似于 with 结构的宏。
用法应该是这样的:
with (lock(&x), unlock(&x)) {
...
}
它可能对其他一些目的有用。
我想出了这个宏:
#define __with(_onenter, _onexit, v) \
for (int __with_uniq##v=1; __with_uniq##v > 0; )\
for (_onenter; __with_uniq##v > 0; _onexit) \
while (__with_uniq##v-- > 0)
#define _with(x, y, z) __with(x, y, z)
#define with(_onenter, _onexit) _with(_onenter, _onexit, __COUNTER__)
它有 3 个嵌套循环,因为它应该:
- 初始化循环计数器(当然仅限 C99)
- 可能初始化变量_onenter(例如
with (int fd=open(..), close(fd))
)
- Allow
break
在代码块内。 (continue
也是允许的。并且宏可以调整为assert()
it out)
我在 XV6 操作系统的代码中使用了它,它看起来非常有用。
我的问题是 - 这样的宏最严重的问题是什么?我的意思是,除了单纯使用 C 宏(尤其是实现新的控制流构造的宏)之外。
到目前为止已经发现了这些缺点/问题:
- 不支持
return
or goto
(但它可以节省一些goto
内核代码中的 s)
- 不支持错误(例如
fd < 0
)。我认为这个是可以修复的。
- 仅限 gnu89 / c99 及以上版本(循环计数器。唯一变量技巧不是必需的)
- 比简单的锁定解锁效率稍低。我相信这是微不足道的。
还有其他问题吗?有没有更好的方法在 C 中实现类似的构造?
这个宏让我害怕。我更喜欢传统方法使用gotos http://blog.regehr.org/archives/894.
这种方法很原始,但大多数 C 程序员都熟悉该模式,如果不熟悉,他们可以通过阅读本地代码来理解它。不存在隐藏行为。结果,它是相当可靠的。
你的宏很聪明,但它对大多数人来说都是新的,并且它带有隐藏的陷阱。新的贡献者必须考虑诸如“不要return
or goto
从 with 块中“和”break
会跳出 with 块,而不是跳出周围循环”。我担心错误会很常见。
如果您可以向编译器添加有关滥用此构造的警告,则平衡将会发生变化。随着铿锵 http://clang.llvm.org/docs/Tooling.html,这似乎是一个选择。在这种情况下,将检测到误用,并且您的代码仍可移植到其他编译器。
如果您愿意限制自己使用 GCC 和 Clang,您可以使用cleanup https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#Common-Variable-Attributes属性。这将使你的例子看起来像这样:
lock_t x = NULL __attribute__((cleanup(unlock)));
lock(&x);
And unlock
当变量超出范围时,将使用指向该变量的指针来调用。这与其他语言功能集成,例如return
and goto
,甚至混合 C/C++ 项目中也有例外。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)