【问题标题】:Extract Argument from C Macro从 C 宏中提取参数
【发布时间】:2015-06-13 21:39:02
【问题描述】:

我有许多由两个逗号分隔的表达式组成的定义,如下所示:

#define PIN_ALARM  GPIOC,14

我想将这些定义的第二个表达式(在上例中为 14 个)传递给一元宏,如下所示:

#define _PIN_MODE_OUTPUT(n)          (1U << ((n) * 2U))

如何提取第二个数字?我想要一个宏,叫它“PICK_RIGHT”,它会为我做这个:

#define PICK_RIGHT(???)   ???

这样我就可以创建一个新的宏来接受我的“PIN”定义:

#define PIN_MODE_OUTPUT(???) _PIN_MODE_OUTPUT(PICK_RIGHT(???))

我可以这样做:

#define RESULT   PIN_MODE_OUTPUT(PIN_ALARM)

【问题讨论】:

  • 只需使用宏来做简单的事情。这就是他们的功能
  • 我会考虑在您的情况下不使用宏,而是使用一些脚本(例如在 POSIX 上的 awk 中)生成 C 代码(在某些标头或某些包含的代码文件中)。或者使用外部预处理器,如GPP
  • 通过分别定义端口和位。无论如何,什么是“一元宏”?
  • 请注意,以下划线和大写字母开头的名称保留给实现使用;你不应该自己创建这样的名字。

标签: c macros arguments c-preprocessor


【解决方案1】:

不要为此使用宏。如果必须,以下将通过首先丢弃左侧部分来工作,因此仅保留数字。小心使用。没有保证。

#define PIN_ALARM  GPIOC,14
#define RIGHTPART_ONLY(a,b) b

#define PIN_MODE_OUTPUT(a) RIGHTPART_ONLY(a)

#define RESULT   PIN_MODE_OUTPUT(PIN_ALARM)

int main (void)
{
    printf ("we'll pick ... %d\n", PIN_MODE_OUTPUT(PIN_ALARM));
    printf ("or maybe %d\n", RESULT);

    return 0;
}

如果您希望将左侧部分作为字符串,您可以使用它(带有与上面相同的警告),其中左侧部分通过# 转换为字符串:

#define LEFTPART_ONLY(a,b) #a
#define PIN_MODE_NAME(a) LEFTPART_ONLY(a)

有一个实际的原因,这并非完全没有问题。 GPIOC 是一个符号,因此它可能在别处定义。幸运的是,如果它是未定义的,或者它只是一个简单的类型,这不是问题——毕竟,宏做的第一件事就是“扔掉左边的部分”。但正如乔纳森·莱弗勒一样

请注意,如果 GPIOC 映射到包含逗号的宏,您可能会遇到编译错误。

【讨论】:

  • +1 出于某种原因,我只是假设这不起作用,没有对其进行测试,即使我知道通过另一个宏在预处理器中扩展它的技巧(对于a##b 类型粘贴)......鉴于它有效,我不确定是否需要“不保证”警告 - 我会说更相关的警告是代码可读性。
  • @Arkku:我不得不尝试多次嵌套宏迭代才能让它工作(其中一个使用了atoi..)。无论如何,对我来说,这感觉太像滥用 C 及其宏——它们不是为这种操作而设计的。
  • 干得好。请注意,如果 GPIOC 映射到包含逗号的宏,您可能会因此得到编译错误(例如,尝试将#define GPIOC 19,13 添加到问题中的代码中)。例如,GCC 抱怨调用带有 3 个参数而不是预期的 2 个参数的宏。
  • @Jongware:你告诉我不要为此使用宏是对的。我采取了将每个 PIN_XXX 定义拆分为单独的端口和引脚定义的丑陋方法。结果更简单,如果更详细的话。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多