使用#define-d列表作为C预处理程序宏的输入 [英] Using a #define-d list as input to a C preprocessor macro

查看:63
本文介绍了使用#define-d列表作为C预处理程序宏的输入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在一个示例项目中,我定义了宏

In an example project, I defined the macro

#define FOO(x, y) x + y   .

这很好用.例如,将 FOO(42,1337)评估为 1379 .

This works perfectly well. For example, FOO(42, 1337) is evaluated to 1379.

但是,我现在想使用另一个 #define :

However, I now want to use another #define:

#define SAMPLE 42, 1337

当我现在呼叫 FOO(SAMPLE)时,这将无法工作.编译器告诉我 FOO 带有两个参数,但是只能使用一个参数调用.

When I now call FOO(SAMPLE), this won't work. The compiler tells me that FOO takes two arguments, but is only called with one argument.

我猜想,这样做的原因是,尽管宏的参数是在函数本身之前进行求值的,但是预处理器不会在求值后再次解析整个指令.这类似于无法从宏输出其他预处理器指令的事实.

I guess that the reason for this is that, although, the arguments of a macro are evaluated in advance of the function itself, that the preprocessor does not parse the whole instruction again after this evaluation. This is a similar to the fact that it is not possible to output additional preprocessor directives from a macro.

是否有可能获得所需的功能?

Is there any possibility to get the desired functionality?

用C函数替换 FOO 宏是不可能的.原始宏位于无法更改的第三方代码中,并且它输出以逗号分隔的值列表,可直接在数组初始化程序中使用.因此,C函数无法复制相同的行为.

Replacing the FOO macro with a C function is not a possibility. The original macro is located in third party code I cannot change, and it outputs a comma-separated list of values to be directly used in array initializers. Therefore, a C function cannot replicate the same behaviour.

如果不可能通过简单的方法来完成此任务:如何以可维护的形式存储(x,y)对?就我而言,有8个参数.因此,将各个部分存储在单独的 #define -s中也不容易维护.

If it is not possible to accomplish this task by using simple means: How would you store the (x, y) pairs in a maintainable form? In my case, there are 8 arguments. Therefore, storing the individual parts in separate #define-s is also not easy maintainable.

推荐答案

您遇到了一个问题,即预处理器无法按所需顺序匹配和扩展宏.现在,您通常可以通过插入一些额外的宏来强制其正确执行订单,从而使其执行所需的操作,但是为此,您需要了解正常的订单是什么.

You're running into a problem where the preprocessor is not matching and expanding macros in the order you want. Now you can generally get it to do what you want by inserting some extra macros to force it to get the order right, but in order to that you need to understand what the normal order is.

  • ,当编译器看到带有参数的宏名称后跟一个()时,它将首先在该参数列表中进行扫描,将其分解为参数,而不会识别或扩展参数中的任何宏.

  • when the compiler sees the name of a macro with arguments followed by a ( it first scans in that argument list, breaking it into arguments WITHOUT recognizing or expanding any macros in the arguments.

在解析并分离了参数之后,它将重新扫描每个参数以查找宏,并使用参数扩展其找到的内容,除非该参数与# ## <一起使用/code>在宏正文中

after parsing and separating the arguments, it then rescans each argument for macros, and expands any it finds withing the argument UNLESS the argument is used with # or ## in the macro body

然后用(现在可能已扩展的)参数替换正文中参数的每个实例

it then replaces each instance of the argument in the body with the (now possibly expanded) argument

最后,它将重新扫描主体以查找可能与主体存在的任何其他宏以进行扩展.在这一扫描中,原始宏将不会被识别和扩展,因此您将无法进行递归宏扩展

finally, it rescans the body for any OTHER macros that may exist with the body for expansion. In this one scan, the original macro WILL NOT be recognized and reexpanded, so you can't have recursive macro expansions

因此,您可以通过谨慎使用EXPAND宏来获得所需的效果,该宏接受单个参数并将其扩展,从而允许您在过程中的正确位置强制进行额外的扩展:

So you can get the effect you want by careful use of an EXPAND macro that takes a single argument and expands it, allowing you to force extra expansions at the right point in the process:

#define EXPAND(X)   X
#define FOO(x,y)    x + y
#define SAMPLE      42, 1337

EXPAND(FOO EXPAND((SAMPLE)))

在这种情况下,您首先在参数列表中显式扩展宏,然后再手动扩展结果宏调用.

In this case you first explicitly expand macros in the argument list, and then manually expand the resulting macro call afterwards.

按问题发帖人更新

#define INVOKE(macro, ...) macro(__VA_ARGS__)

INVOKE(FOO, SAMPLE)

提供了一种扩展的解决方案,该解决方案无需使用 EXPAND s使代码混乱.

provides an extended solution that works without cluttering the code with EXPANDs.

这篇关于使用#define-d列表作为C预处理程序宏的输入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆