【问题标题】:C preprocessor: Is there any way to expand the name of a macro inside itselfC预处理器:有什么方法可以在自身内部扩展宏的名称
【发布时间】:2016-05-16 06:59:21
【问题描述】:

我想要一个打印它自己的名称(以及其他内容)的宏,但我找不到在宏本身中扩展宏名称的方法。基本上,我想要一个相当于 __FUNCTION__ 的宏名称。

例如:

#define F(a, b, c) do { \
   printf("%s: %s,%s,%s\n", __MACRO__, #a, #b, #c); \
   c = a+b; b=a; \
} while(0)

F(x,y,z); 

我希望它在调用时打印“F: x,y,z”。


这确实是一个 XY 问题。

这就是我真正想做的事情:使用 dlopen 和 dlsyms 从库中软链接符号。

为了做到这一点,我知道的典型方式是: 1)包括库中的标题。 2) 声明您尝试导入的函数类型的变量 3) 调用 dlsym 初始化所述变量 4) 通过该变量调用实际函数,而不是直接调用符号。

当你有很多这样的函数来软链接时,它变得非常重复,所以宏可以帮助。

有关这方面的完整示例,请参见此处:https://github.com/WebKit/webkit/blob/master/Source/WebCore/platform/mac/SoftLinking.h

该示例和其他示例中的问题是您仍然需要为每个要软链接的函数手动复制参数列表。 我正在尝试改进这一点,并且正在尝试使用宏观技巧,其中一个可以通过回答我最初的问题得到帮助。

--

除了我的软链接问题之外,还有其他可能有用的情况。例如,出于调试目的,可能希望在每次调用某些函数之前或之后打印一些诊断信息。可以通过用宏覆盖函数名称来做到这一点:

#define funcA(...) \
printf("Before call to %s:%d - %d\n", #funcA, __LINE__, g_count); \
funcA(__VA_ARGS__) \
printf("After call to %s:%d - %d\n", #funcA, __LINE__, g_count);

这很好用,但是如果我想为一堆函数执行此操作,我必须复制该宏并将每个新宏的 funcA 更改为 funcB 4 次。我宁愿复制它并只更改宏的名称,而不必更改里面的内容。

我可以通过定义一个内部宏 p 来优化上述内容,类似于 Basile 的建议:

#define funcA(...) WRAP(funcA, __VA_ARGS__)

但这仍然意味着每次我为另一个函数复制宏时,我都需要将 funcA 更改为新的函数名两次。

【问题讨论】:

  • 你为什么想让你的代码不可读和更难调试?为什么有些人喜欢预处理器。它适合做简单的事情。
  • 嗯,这个例子太简单了。在我的实际用例中,“printf”实际上会嵌入到另一个宏中,例如 #define P(f, ...) printf("%s%s\n", f, __VA_ARGS__)
  • @EdHeal 我实际上是在尝试避免多次复制粘贴模式。
  • 宏很难调试。他们混淆了代码。他们没有编译器喜欢的类型机制的奢侈。为什么要使用它们?
  • 感谢@EdHeal 的建议,但在这种情况下这无济于事。

标签: c c-preprocessor


【解决方案1】:

阅读有关C preprocessor 的更多信息。阅读GNU cpp 的文档。注意它的stringificationconcatenation 能力。

也许通过一些额外的内部宏可能会对你有所帮助,所以你可能有一个公共宏,比如

 #define FOO(X,Y,Z) PRIVATE_FOO(FOO,X,Y,Z)

可能还有另一个PRIVATE_FOO 宏对其第一个参数进行字符串化技巧

#define PRIVATE_FOO(Mac,X,Y,Z) do { \
 printf("%s: %s,%s,%s\n", #Mac, #X, #Y, #Z); \
 Z = X+Y; Y=X; \
} while(0)

也许 C 预处理器不足以完成您的任务。您可以使用其他工具生成一些 C 代码(可能是 GPP 预处理器,或者可能是简单的 awkpython 脚本,或者可能是一些真正的程序;您需要更改构建过程,例如您的 @ 987654334@,处理)。如果需要,您可以使用 MELT 自定义您的 GCC 编译器。由于我们不知道您的实际动机,因此我们无法提供更多帮助。

除非您激发并澄清您的问题,否则我无法提供更多帮助。

您的软链接问题只需使用一些weak symbols。它可能与 C 预处理无关。

【讨论】:

  • 没有弱符号或弱链接与软链接是不同的问题,至少在我的平台(OS X)上是这样。特别是,当软链接(如上所述)时,您不需要在构建时拥有软链接的库,而在弱链接时仍然需要它。
  • 关于您对内部宏的评论,这确实是我正在尝试使用的,这也是我想要获取宏名称的原因。
猜你喜欢
  • 2020-10-18
  • 2018-01-04
  • 2011-03-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-27
  • 1970-01-01
  • 2018-05-12
相关资源
最近更新 更多