C 中的“with”宏

2024-04-10

我一直在寻找一个类似于 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 个嵌套循环,因为它应该:

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

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

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

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

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

还有其他问题吗?有没有更好的方法在 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(使用前将#替换为@)

C 中的“with”宏 的相关文章

随机推荐

  • 如何在 Eclipse 中找到方法实现的用法?

    当我想在java中找到普通方法的用法时 这是相当简单和直接的CTRL SHIFT G 但是如果这个方法有一个super定义 实现 Eclipse 将向我展示层次结构类型中所有类型的用法 例如 如果我有一个toString 方法在我的类中 我
  • 将 ViewChild 用于动态元素 - Angular 2 和 ionic 2

    我想使用多个离子载玻片 https ionicframework com docs api components slides Slides 我动态添加的 但我不能使用 viewChild 请提出解决此问题的方法 模板 html div d
  • 如何使用 My.Settings.Save Visual Basic 保存窗体背景图像

    我正在尝试用 Visual Basic 创建一个操作系统 当然是基于程序的 它需要个性化 我希望用户能够从存储在项目资源中的一组选定图像中进行选择 并且我希望保存该图像 以便他们下次登录软件时 表单具有相同的他们选择保存的图像 额外的信息
  • python中的IOE错误“没有这样的文件或目录”

    我正在编写一个 Django 项目 涉及从表中检索数据 我有一个模块 它具有检索一些数据的行 snp data txt是模块同一目录中的文件 data file snp data txt 当我在 django 项目之外单独调用该模块时 该模
  • 整数求和布鲁斯,短+=短问题

    C 程序 short a b a 10 b 10 a a b Error Cannot implicitly convert type int to short we can also write this code by using Ar
  • 允许重复键并保持插入顺序的映射

    目前我正在使用 LinkedHashMap 来维护插入顺序 我使用的 LinkedHashMap 的语法 private LinkedHashMap
  • 防止mysql中的值变为负数的最佳方法

    我们有一个表 通过在该表中记录交易来维护帐户余额 即最近一行是帐户余额 在记录提款时 我们希望确保余额 永远不会出现负数 我们提出的解决方案类似于 INSERT INTO txns account id prev balance txn t
  • WinFORMS 中的 WPF 用户控件:项目结构

    SCENARIO 我决定为我的新应用程序使用 WPF 技术 必须通过从 WinForms 窗口单击菜单来调用此应用程序 因此 我创建了一个 WPF UserControl 库 并将其集成以使用 Element Host 在父 WinForm
  • 如何将数组转换为 UnsafeMutablePointer Swift 3.0?

    这是我在以前版本的 Swift 中的可行代码 let imageOptionsDictKeys kCVPixelBufferPixelFormatTypeKey kCVPixelBufferWidthKey kCVPixelBufferHe
  • 如何通过 lambda 函数 aws 发送和返回 JSON 响应

    我有一个名为 lambda 函数的 Amazon Webservices 闭包 其委托定义如下 def lambda handler event context logger info Ev s event if event action
  • 从 pandas 数据框中删除具有空值的行

    我正在尝试从数据框中删除一行 其中其中一列的值为空 我能找到的大部分帮助都与删除 NaN 值有关 到目前为止 这对我不起作用 我在这里创建了数据框 successfully crated data frame df1 ut get data
  • Opencv 图像拼接或全景

    我正在 OpenCV 全景 中进行图像拼接 但有一个问题 我无法使用 OpenCV 中的 Stitching 类 因此我必须仅使用特征点和单应性来创建它 OrbFeatureDetector detector minHessian std
  • querySelectorAll 是否支持 id 中的句点(.) 字符?

    querySelectorAll 是否支持 id 中的句点 字符 我的意思是如果我附加一个如下所示的元素 var div document createElement div div id my divid document body ap
  • Java 8 findFirst().isPresent() 比 count() > 0 更高效吗?

    鉴于我有一个流Stream
  • 如何在 CAFFE 的新网络中重复使用同一网络两次

    我有一个预训练的网络 我们称之为N 我想在新网络中使用两次 有人知道如何复制吗 然后我想为每个副本分配不同的学习率 例如 N1是第一个副本N N2是第二个副本N 新网络可能如下所示 N1 gt joint ip N2 gt layer 我知
  • 如何使用 vanilla JS 复制 useState

    Vanilla JS 中的代码的实现是什么 它允许我们像 React 中的 useState 那样声明和更新状态 const x setX useState 12 setX 14 console log x 14 这道题严格来说是get b
  • Android 1.5 多点触控

    有谁知道是否可以在 Android 1 5 设备上使用多点触控 我有一台 HTC Hero 它仍然运行 1 5 HTC 在推出 2 1 ROM 方面有点慢 Android MotionEvent 文档显示了常量 ACTION POINTER
  • android TextView:动态设置背景颜色不起作用

    以编程方式设置 Android 的背景颜色TextView似乎不起作用 我是不是漏掉了一些东西 TextView et new TextView activity et setText 350 et setBackgroundColor R
  • 使用 union 插入表变量

    我有一个表变量 我想插入联合查询 联合查询运行良好 但我似乎无法使插入工作 语法错误 INSERT INTO table a b c d VALUES SELECT a b c d FROM table1 UNION SELECT a b
  • C 中的“with”宏

    我一直在寻找一个类似于 with 结构的宏 用法应该是这样的 with lock x unlock x 它可能对其他一些目的有用 我想出了这个宏 define with onenter onexit v for int with uniq