【问题标题】:"with" macro in CC中的“with”宏
【发布时间】:2013-04-24 16:59:25
【问题描述】:

我正在寻找一个类似于 with-construct 的宏。 用法应该是这样的:

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 个嵌套循环,因为它应该:

  1. 初始化循环计数器(当然仅限 C99)
  2. 可能初始化变量_onenter(如with (int fd=open(..), close(fd))
  3. 在代码块中允许break。 (continue 也是允许的。宏可以调整为assert() 出来)

我在 XV6 操作系统的代码上使用了它,它看起来很有用。

我的问题是 - 这种宏最严重的问题是什么?我的意思是,除了仅仅使用 C 宏(尤其是实现新的控制流结构的宏)之外。

到目前为止已经发现了这些缺点/问题:

  1. 不支持returngoto(但它可以在内核代码中节省一些gotos)
  2. 不支持错误(例如fd < 0)。我认为这个是可以修复的。
  3. 仅限 gnu89 / c99 及以上版本(循环计数器。不需要唯一变量技巧)
  4. 比简单的锁定解锁效率稍低。我认为它微不足道。

还有其他问题吗?有没有更好的方法在 C 中实现类似的构造?

【问题讨论】:

    标签: c c-preprocessor with-statement


    【解决方案1】:

    那个宏吓到我了。我更喜欢traditional approach using gotos

    这种方法很原始,但大多数 C 程序员都熟悉这种模式,如果不熟悉,他们可以通过阅读本地代码来理解它。没有隐藏的行为。因此,它非常可靠。

    你的宏很聪明,但它对大多数人来说都是新的,它带有隐藏的陷阱。必须考虑新贡献者的规则,例如“不要将 returngoto 超出 with 块”和“break 将脱离 with 块,而不是超出周围的循环”。我担心错误会很常见。

    如果您可以向编译器添加有关滥用此构造的警告,那么平衡就会发生变化。 With clang,这似乎是一种选择。在这种情况下,会检测到误用,并且您的代码仍可移植到其他编译器。

    如果您愿意将自己限制在 GCC 和 Clang,您可以使用 cleanup 属性。这将使您的示例看起来像这样:

    lock_t x = NULL __attribute__((cleanup(unlock)));
    lock(&x);
    

    当变量超出范围时,unlock 将被调用,并带有指向变量的指针。这与 returngoto 等其他语言功能集成,甚至在混合 C/C++ 项目中也有例外。

    【讨论】:

    • 哦。最后回复...谢谢,我不知道cleanup - 听起来很有用。除了可怕之外,宏是否还有更具体的问题?
    • 缺乏对return 的支持似乎是一个交易破坏者,除非您使用严格的编码标准来处理函数中间的return 语句。 with 块中的 return 看起来不起眼,但会在运行时造成严重破坏。
    • 我理解并同意return 是一个大问题(所以cleanup 要好得多)。但是goto 不是要求同样严格的编码标准吗? goto 在这方面有什么优势?
    • Gotos,正如我链接到的文章中所使用的,是原始的,但大多数 C 程序员都熟悉这种模式并且没有隐藏的行为。因此,它非常可靠。你的宏对大多数人来说都是新的,它带有隐藏的陷阱。这完全取决于程序员学习规则的速度和可靠性,例如“不要将returngoto 超出with 块”和“break 将突破with 块,而不是退出周围的循环”。
    • 所以你说的就像,gotos 是一个警告标志,用户定义的宏不是。好的。
    猜你喜欢
    • 1970-01-01
    • 2016-09-05
    • 1970-01-01
    • 2018-10-17
    • 2012-03-07
    • 1970-01-01
    • 2012-11-30
    相关资源
    最近更新 更多