Hacker News 中文摘要

RSS订阅

C语言中的递归宏,揭秘(一旦丑陋的哭泣停止) -- Recursive macros in C, demystified (once the ugly crying stops)

文章摘要

这篇文章探讨了C语言中递归宏的复杂性和挑战。作者指出,尽管C的宏系统设计存在缺陷且难以驾驭,但作为C语言唯一的编译时执行能力,它对于许多关键系统仍然至关重要。宏虽然看似简单,但存在许多微妙问题,使其仅适合轻量级封装。作者以30年C语言经验坦言,宏系统是C语言中最令人不适的部分,但又是不可或缺的抽象工具。

文章总结

C语言递归宏解析:从崩溃到理解 😭

文章概述

本文深入探讨了C语言预处理器中递归宏的实现原理与技巧。作者通过构建一个计算可变参数宏参数数量的案例,揭示了C宏系统反直觉的设计哲学和令人抓狂的限制。

核心内容

C宏系统的设计缺陷

  • C预处理器(CPP)不支持直接递归,宏展开时会标记为"蓝色"(不可再展开)
  • 预处理器与编译器完全分离,导致错误信息难以理解
  • 宏展开规则复杂且文档不足,调试极其困难

递归宏的实现技巧

作者通过以下步骤实现了递归计数宏: 1. 使用__VA_OPT__处理可变参数 2. 通过EMPTY()POSTPONE宏延迟展开 3. 创建多层EVAL宏强制重新扫描 4. 最终方案封装为H4X0R_MAPH4X0R_VA_COUNT

实用案例

展示了如何将这套机制应用于: - 可变参数计数 - 类型安全转换(H4X0R_VA_VOID_STAR_CONVERT) - 参数遍历处理

对C标准的建议

作者呼吁C标准委员会改进: 1. 添加__VA_COUNT__内置宏 2. 提供__VA_EMPTY__反向条件宏 3. 引入__VA_EVAL__完全展开指令 4. 考虑增加__MAP____SHA256__实用宏

技术细节

关键宏实现

```c

define H4X0R_EVAL(...) // 多层嵌套展开宏

define H4X0RPOSTPONE1(macro) macro H4X0REMPTY() // 延迟展开

define H4X0R_MAP(macro, ...) // 参数遍历框架

define H4X0RVACOUNT(...) // 最终参数计数器

```

典型错误模式

直接递归尝试会失败: ```c

define COUNT(x,...) 1 + COUNT(VA_ARGS) // 无法工作

```

解决方案原理

通过间接调用和延迟展开绕过"蓝色标记"限制,使用EVAL强制多次扫描直到完全展开。

总结

本文以幽默而深刻的方式揭示了C宏系统的底层机制,提供了实用的递归宏实现模式,并指出了语言设计的改进方向。尽管过程痛苦,但最终以18行精炼代码实现了强大的编译时计算能力。

评论总结

以下是评论内容的总结:

  1. 关于宏扩展的技术讨论

    • 用户询问是否能用宏技术实现多函数调用(评论1)
    • 有人分享递归宏扩展的GCC实现代码片段(评论2)
      引用:"Can I use this technique to expand MACRO(a,b,c,…) into something like F(a,b,c…); G(a,b,c…)?"
      引用:"There you can find a recursive macro expansion implementation (as a gcc hack) that fits on a slide"
  2. 对C预处理器的批评与反思

    • 有用户因复杂性放弃编写预处理器(评论3)
    • 批评C宏的行为缺乏标准规范(评论4)
      引用:"I stopped writing it after that"
      引用:"The behavior of C macros is actually described by a piece of pseudocode... and it is not in the standard"
  3. 安全性与极端案例

    • 担忧宏可能导致构建无限循环(评论5)
    • 对用宏实现SHA256表示震惊(评论6)
      引用:"Is this a DoS risk - code that sends your build chain into an infinite loop?"
      引用:"I wept when the author mentioned implementing SHA256 in macros."
  4. 替代方案与历史背景

    • 提及未被采纳的VA_TAIL提案(评论7)
    • 讨论C预处理器设计可能受早期宏工具(如m4)影响(评论14)
      引用:"IMO very well thought out, but unfortunately not accepted"
      引用:"I suspect the difficulty in doing things like this is intentional"
  5. 开发者体验两极分化

    • 有开发者称C预处理器用户为"受虐狂"(评论11)
    • 也有人认为其限制性反而避免更严重的滥用(评论12)
      引用:"Anyone who uses it is a masochist"
      引用:"being limited ends up being a feature"

注:所有评论均无评分(None),故未体现认可度差异。总结保留了技术讨论、批评反思、安全警告等多元视角,并采用简洁中文呈现核心观点。