我如何在 ANSI C 中实现类似于 Objective-C @encode() 编译器指令的东西?

2024-05-10

@encode 指令返回一个 const char *,它是传入的数据类型的各个元素的编码类型描述符。示例如下:

struct test
{ int ti ;
  char tc ;
} ;

printf( "%s", @encode(struct test) ) ;
// returns "{test=ic}"

我可以看到使用 sizeof() 来确定原始类型 - 如果它是一个完整的对象,我可以使用类方法进行内省。

但是,它如何确定不透明结构的每个元素?


@Lothars 的答案可能是“愤世嫉俗的”,但不幸的是,它非常接近目标。为了实现类似的东西@encode(),您需要一个完整的解析器才能提取类型信息。好吧,至少对于“琐碎”以外的事情@encode()声明(即@encode(char *))。现代编译器通常具有两个或三个主要组件:

  • 前端。
  • 中间端(对于某些编译器)。
  • 后端。

前端必须解析所有源代码,并将源代码文本基本上转换为内部的“机器可用”形式。

后端将内部的“机器可用”形式转换为可执行代码。

具有“中间端”的编译器通常这样做是因为某些需要:它们支持多个“前端”,可能由完全不同的语言组成。另一个原因是为了简化优化:所有优化过程都在相同的中间表示上工作。这gcc编译器套件是“三阶段”编译器的一个示例。llvm可以被认为是“中间和后端”阶段编译器:“低级虚拟机”是中间表示,并且所有优化都以这种形式进行。llvm还能够将其保留在这个中间表示中直到最后一秒 - 这允许“链接时间优化”。这clang编译器实际上是一个(有效)输出的“前端”llvm中间表示。

所以,如果你想添加@encode()功能到“现有”编译器,您可能必须将其作为“源到源”“编译器/预处理器”。这就是最初的 Objective-C 和 C++ 编译器的编写方式——它们解析输入源文本并将其转换为“纯 C”,然后将其输入到标准 C 编译器。有几种方法可以做到这一点:

自己滚动

  • Use yacc and lex组装一个 ANSI-C 解析器。你需要语法——ANSI C 语法 (Yacc) http://www.lysator.liu.se/c/ANSI-C-grammar-y.html是一个好的开始。事实上,要明确的是,当我说yacc,我真的是说bison http://www.gnu.org/software/bison/ and flex。而且,松散地,其他各种yacc and lex比如基于 C 的工具:lemon http://www.hwaci.com/sw/lemon/, dparser http://dparser.sourceforge.net/, etc...
  • Use perl with Yapp http://search.cpan.org/~fdesar/Parse-Yapp-1.05/lib/Parse/Yapp.pm or EYapp http://search.cpan.org/~casiano/Parse-Eyapp-1.157/lib/Parse/Eyapp.pod,它们是伪yacc克隆于perl。与基于 C 的相比,可能更适合快速构建想法原型yacc and lex- it's perl毕竟:正则表达式、关联数组、无内存管理等。
  • 构建你的解析器Antlr http://www.antlr.org/。我对这个工具链没有任何经验,但它是另一个“编译器编译器”工具,(似乎)更适合java开发人员。似乎有免费的 C 和 Objective-C 语法可供使用。

破解另一个工具

Note:我没有使用任何这些工具执行诸如添加之类的个人经验@encode(),但我怀疑它们会很有帮助。

  • CIL http://hal.cs.berkeley.edu/cil/- 没有使用此工具的个人经验,但设计用于解析 C 源代码,然后用它“做事”。根据我从文档中收集到的信息,该工具应该允许您提取所需的类型信息。
  • Sparse http://sparse.wiki.kernel.org/index.php/Main_Page- 值得一看,但不确定。
  • clang http://clang.llvm.org/- 尚未将其用于此目的,但据称目标之一是使其“易于破解”以用于此类内容。特别是(再次强调,没有个人经验)在进行所有解析的“繁重工作”时,让您专注于“有趣”的部分,在这种情况下将提取上下文和语法敏感的类型信息,然后将其转换为到一个普通的 C 字符串。
  • 海湾合作委员会插件 http://gcc.gnu.org/onlinedocs/gccint/Plugins.html#Plugins- 插件是 gcc 4.5(编译器当前的 alpha/beta 版本)功能,“可能”允许您轻松连接到编译器以提取您需要的类型信息。不知道插件架构是否允许这种事情。

Others

  • 科奇内勒 http://Coccinelle.lip6.fr/- 最近将此添加为书签以“稍后查看”。这个“也许”能够做到你想要的,并且“也许”不费吹灰之力就能做到。
  • MetaC http://www.rcs.ei.tum.de/research/MetaC/index_html- 最近也为这个添加了书签。不知道这会有多大用处。
  • mygcc http://mygcc.free.fr/- “可能”做你想做的事。这是一个有趣的想法,但它并不直接适用于你想要的。来自网页:“Mygcc 允许程序员添加自己的检查,考虑语法、控制流和数据流信息。”

Links.

  • CocoaDev Objective-C 解析 http://www.cocoadev.com/index.pl?ObjectiveCParser- 值得一看。有一些词法分析器和语法的链接。

编辑#1,奖励链接。

@Lothar 在他的评论中提出了一个很好的观点。我实际上本来打算包括lcc,不过看起来好像迷路了。

  • lcc http://sites.google.com/site/lccretargetablecompiler/ - The lccC 编译器。这是一个特别小的C编译器,至少在源代码大小方面是这样。它也是有书 https://rads.stackoverflow.com/amzn/click/com/0805316701,我强烈推荐。
  • tcc http://bellard.org/tcc/ - The tccC 编译器。不太有教学意义lcc,但绝对还是值得一看的。
  • poc http://www.ibiblio.org/pub/Linux/devel/lang/objc/ - The pocObjective-C 编译器。这是一个“源到源”的 Objective-C 编译器。它解析 Objective-C 源代码并生成 C 源代码,然后将其传递给gcc(嗯,通常gcc)。具有许多 Objective-C 扩展/功能,这些扩展/功能在gcc。绝对值得一看。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

我如何在 ANSI C 中实现类似于 Objective-C @encode() 编译器指令的东西? 的相关文章

  • 维护 UISegmentedControl 中的选择

    我可以保持 UISegmentViewControl 段的选定状态吗 即 即使用户选择了另一个段 也可以保持一个段显示为选中状态 我似乎在任何地方都找不到任何可以做到这一点的东西 这是不可能开箱即用的 看如何才能选择 UISegmented
  • 自动从 C# 代码进行调试过程并读取寄存器值

    我正在寻找一种方法来读取某个地址的 edx 注册表 就像这个问题中所问的那样 读取eax寄存器 https stackoverflow com questions 16490906 read eax register 虽然我的解决方案需要用
  • Signalr 在生产服务器中总是陷入长轮询

    当我在服务器中托管应用程序时 它会检查服务器端事件并始终回退到长轮询 服务器托管环境为Windows Server 2012 R1和IIS 7 5 无论如何 我们是否可以解决这个问题 https cloud githubuserconten
  • Func 方法参数的首选命名约定是什么?

    我承认这个问题是主观的 但我对社区的观点感兴趣 我有一个缓存类 它采用类型的缓存加载器函数Func
  • C# 中值类型和引用类型有什么区别? [复制]

    这个问题在这里已经有答案了 我知道一些差异 值类型存储在堆栈上 而引用类型存储在托管堆上 值类型变量直接包含它们的值 而引用变量仅包含对托管堆上创建的对象位置的引用 我错过了任何其他区别吗 如果是的话 它们是什么 请阅读 堆栈是一个实现细节
  • 如何在 WPF RichTextBox 中跟踪 TextPointer?

    我正在尝试了解 WPF RichTextBox 中的 TextPointer 类 我希望能够跟踪它们 以便我可以将信息与文本中的区域相关联 我目前正在使用一个非常简单的示例来尝试弄清楚发生了什么 在 PreviewKeyDown 事件中 我
  • c 中的错误:声明隐藏了全局范围内的变量

    当我尝试编译以下代码时 我收到此错误消息 错误 声明隐藏了全局范围内的变量 无效迭代器 节点 根 我不明白我到底在哪里隐藏或隐藏了之前声明的全局变量 我怎样才能解决这个问题 typedef node typedef struct node
  • C# 用数组封送结构体

    假设我有一个类似于 public struct MyStruct public float a 我想用一些自定义数组大小实例化一个这样的结构 在本例中假设为 2 然后我将其封送到字节数组中 MyStruct s new MyStruct s
  • HttpClient 像浏览器一样请求

    当我通过 HttpClient 类调用网站 www livescore com 时 我总是收到错误 500 可能服务器阻止了来自 HttpClient 的请求 1 还有其他方法可以从网页获取html吗 2 如何设置标题来获取html内容 当
  • 当 Cortex-M3 出现硬故障时如何保留堆栈跟踪?

    使用以下设置 基于 Cortex M3 的 C gcc arm 交叉工具链 https launchpad net gcc arm embedded 使用 C 和 C FreeRtos 7 5 3 日食月神 Segger Jlink 与 J
  • 为什么模板不能位于外部“C”块内?

    这是一个后续问题一个答案 https stackoverflow com questions 4866433 is it possible to typedef a pointer to extern c function type wit
  • 在 ASP.Net Core 2.0 中导出到 Excel

    我曾经使用下面的代码在 ASP NET MVC 中将数据导出到 Excel Response AppendHeader content disposition attachment filename ExportedHtml xls Res
  • 使用 LINQ 查找列表中特定类型的第一个元素

    使用 LINQ 和 C 在元素列表中查找特定类型的第一个项目的最短表示法是什么 var first yourCollection OfType
  • 什么是 C 语言的高效工作流程? - Makefile + bash脚本

    我正在开发我的第一个项目 该项目将跨越多个 C 文件 对于我的前几个练习程序 我只是在中编写了我的代码main c并使用编译gcc main c o main 当我学习时 这对我有用 现在 我正在独自开展一个更大的项目 我想继续自己进行编译
  • 在 URL 中发送之前对特殊字符进行百分比编码

    我需要传递特殊字符 如 等 Facebook Twitter 和此类社交网站的 URL 为此 我将这些字符替换为 URL 转义码 return valToEncode Replace 21 Replace 23 Replace 24 Rep
  • ListDictionary 类是否有通用替代方案?

    我正在查看一些示例代码 其中他们使用了ListDictionary对象来存储少量数据 大约 5 10 个对象左右 但这个数字可能会随着时间的推移而改变 我使用此类的唯一问题是 与我所做的其他所有事情不同 它不是通用的 这意味着 如果我在这里
  • 方法参数内的变量赋值

    我刚刚发现 通过发现错误 你可以这样做 string s 3 int i int TryParse s hello out i returns false 使用赋值的返回值是否合法 Obviously i is but is this th
  • 更改显示的 DPI 缩放大小使 Qt 应用程序的字体大小渲染得更大

    我使用 Qt 创建了一些 GUI 应用程序 我的 GUI 应用程序包含按钮和单选按钮等控件 当我运行应用程序时 按钮内的按钮和字体看起来正常 当我将显示器的 DPI 缩放大小从 100 更改为 150 或 200 时 无论分辨率如何 控件的
  • 如何连接字符串和常量字符?

    我需要将 hello world 放入c中 我怎样才能做到这一点 string a hello const char b world const char C string a hello const char b world a b co
  • 为什么 strtok 会导致分段错误?

    为什么下面的代码给出了Seg 最后一行有问题吗 char m ReadName printf nRead String s n m Writes OK char token token strtok m 如前所述 读取字符串打印没有问题 但

随机推荐