【问题标题】:How do we use nested if else with #define preprocessor我们如何在 #define 预处理器中使用嵌套 if else
【发布时间】:2020-06-07 15:27:29
【问题描述】:
#define len(a) if (a == 8)   1       \
               else if (a == 3) 0    \
               else -1

这段代码只是我们如何使用嵌套 if else 的示例。 我不想使用三元运算符,因为在这种情况下我不能使用 else if 语句。

【问题讨论】:

  • 使用函数。
  • 为什么要为此使用预处理器?
  • 如果你能在我竞争对手的代码库中这样做,我将不胜感激。
  • 我只是想学习如何使用预处理器来做到这一点 #define len(a) [](int x) -> int { if (x == 8) return 1; if (x == 3) return 0; return -1; }(a) 既然你已经学会了,我也希望你学会了不要去做吧。
  • 选择一个标签,C 或 C++。

标签: c++ c c-preprocessor


【解决方案1】:

不要滥用预处理器。使用实函数:

constexpr auto len(int const a) {
    if (a == 8) return 1;
    if (a == 3) return 0;
    return -1;
}

【讨论】:

  • @Ray 如果提供的参数是一个常量表达式,结果也将在编译时计算。如果不是,结果也不是。
  • @_Static_assert,它可以,但是要强制它在编译时完成,您需要在需要常量表达式的上下文中使用结果。跨度>
  • @chr 是的,你是对的。我想大多数编译器无论如何都会做这种优化。即使参数不是 constexpr,它也可能是内联的。所以这与预处理完全相同,但编写/使用/维护更方便。
  • 它只是 C++。不会编译为 C
  • @P__J__ 你可以定义一个宏#ifndef __cplusplus #define constexpr #endif。所以你无法判断它是否是有效的 C。
【解决方案2】:
inline __attribute__((always_inline)) int len(const int a)
{
    switch(a)
    {
        case 8: return 1;
        case 3: return 0;
    }
    return -1;
}

【讨论】:

  • 我从来没有用过 C++ 编程,我想我把 constexprinline 混在一起了。
  • 据我了解,它必须是有效的 C 和 C++
  • 请注意,__attribute__((always_inline)) 是非标准的,并不适用于所有编译器。
【解决方案3】:

如果您可以使用 GNU 扩展并坚持使用带有 if-else 分支的宏,则可以使用 compound statement expression

#define len(a) ({                 \
    int _res = -1;                \
    if ((a) == 8) _res = 1;       \
    else if ((a) == 3) _res = 0;  \
    (_res); })

这适用于 C 和 C++。不幸的是,这样的复合语句不能用在常量表达式中。

【讨论】:

  • 所以这就像using a lambda,但不可移植?
  • @_Static_断言,不完全等效。在那个 lambda 中,a 只被评估一次,在这里它可以被评估两次。这很容易解决。而且 C 中没有 lamdas。
【解决方案4】:

Re:“我不想使用三元运算符,因为在这种情况下我不能使用 else if 语句”——嗯,是的,你不能在三元运算符中使用 else if。但是你可以使用另一个三元运算符:

int x = a == 8 ? 1
    : a == 3 ? 0
    : -1;

【讨论】:

    【解决方案5】:

    在宏中编写嵌套或非if 语句没有问题,或者当您尝试将语句包装在宏中时,至少没有比平常更多的问题。但请注意,我使用了语句,在 C 或 C++ 中没有 if 表达式之类的东西,除了您不想使用的三元运算符。

    所以如果你想在宏中嵌套ifs 语句,你可以这样做

    #define stmt(c1, c2) \
       if (c1) \
          do_1(); \
       else if (c2) \
          do_2(); \
       else \
          do_3()
    

    (请注意,转义行尾的方法是使用\,而不是使用/)。如果您想要一个表达式,则必须使用三元运算符或其他答案中显示的函数。好吧,即使你需要语句,我还是建议使用函数而不是宏。

    【讨论】:

    • 除了让代码难以调试和阅读之外,我找不到任何理由这样做
    • @AProgrammer 所有其他答案都涵盖了这一点。这不切实际。
    • @P__J__ 你在我添加一个事实时评论说,即使对于语句,我也会推荐一个函数。
    • @AProgrammer 总是建议在提交之前等待完成您的完整答案。这样以后就可以避免这个问题了。
    猜你喜欢
    • 2011-02-19
    • 2021-10-12
    • 1970-01-01
    • 2023-01-31
    • 2016-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-12
    相关资源
    最近更新 更多