Ela*_*zar 5 c with-statement c-preprocessor
我正在寻找一个类似于with-construct的宏.用法应该是这样的:
with (lock(&x), unlock(&x)) {
...
}
Run Code Online (Sandbox Code Playgroud)
它可能对其他一些用途有用.
我想出了这个宏:
#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__)
Run Code Online (Sandbox Code Playgroud)
它有3个嵌套循环,因为它应该:
with (int fd=open(..), close(fd)))break在代码块内部.(continue也是允许的.宏可以调整到assert()它)我在XV6操作系统的代码上使用它,它看起来非常有用.
我的问题是 - 这样一个宏的最大问题是什么?我的意思是,除了仅仅使用C宏(特别是实现新的控制流构造的宏).
到目前为止已发现这些缺点/问题:
return或goto(但它可以goto在内核代码中保存一些内容)fd < 0).我认为这个是可以解决的.还有其他问题吗?有没有更好的方法在C中实现类似的构造?
这种方法很原始,但大多数C程序员都熟悉这种模式,如果不是,他们可以通过阅读本地代码来理解它.没有隐藏的行为.因此,它非常可靠.
你的宏很聪明,但它对大多数人来说都是新的,它带有隐藏的陷阱.新的贡献者必须被认为是规则,例如"不要return或goto不使用块"和" break将突破with块,而不是从周围的循环中".我担心错误会很常见.
如果您可以将错误使用此构造的警告添加到编译器,那么余额将会发生变化.有了clang,这似乎是一种选择.在这种情况下,将检测到误用,并且您的代码将保持可移植到其他编译器.
如果您愿意将自己限制为GCC和Clang,则可以使用该cleanup属性.这会使你的例子看起来像这样:
lock_t x = NULL __attribute__((cleanup(unlock)));
lock(&x);
Run Code Online (Sandbox Code Playgroud)
并且unlock将与指针变量,当它超出范围被调用.这与其他语言功能(如return和goto,甚至是混合C/C++项目中的例外)集成在一起.