【问题标题】:How to pass string as prefix of defined macro如何将字符串作为已定义宏的前缀传递
【发布时间】:2021-09-24 08:00:23
【问题描述】:

有没有办法像下面的代码一样将 C 字符串作为定义的宏的一部分传递?

#define AAA_NUM 10
#define BBB_NUM 20
#define PREFIX_NUM(string) string##_NUM

int main()
{
    char *name_a = "AAA";
    char *name_b = "AAA";
    printf("AAA_NUM: %d\n", PREFIX_NUM(name_a));
    printf("BBB_NUM: %d\n", PREFIX_NUM(name_b));

    return 0;
}

预期输出

AAA_NUM: 10
BBB_NUM: 20

【问题讨论】:

  • name_aname_b 的值对预处理器不可用,因此您的宏实际上看到了名称 name_aname_b。您可以将它们转换为string_name_astring_name_b,但这显然不是您想要的。您需要了解预处理器在解析 C 代码之前执行简单的文本翻译。一旦你理解了这一点,你就会明白为什么这不能达到你想要的效果。
  • 我认为您正在尝试提出一个答案而没有该答案解决的问题......您到底需要这个做什么?

标签: c macros


【解决方案1】:

正如其他帖子中提到的,您不能在预处理器中使用运行时变量。但是,您可以通过这种方式创建 enum。尽管使用宏生成标识符通常也不是一个好主意,但在特殊情况下除外,例如在维护现有代码库时,您可以/想要更改多少现有代码。所以它只能作为最后的手段。

编写此类宏最不坏的方法是使用一种称为“X 宏”的通用设计模式。当需要将代码重复减少到项目中的单个位置很重要时,使用这些。他们倾向于使代码看起来相当陌生......示例:

#define PREFIX_LIST(X) \
/*  pre  val */        \
  X(AAA, 10)           \
  X(BBB, 20)           \
  X(CCC, 30)           \

enum // used to generate constants like AAA_NUM = 10,
{
  #define PREFIX_ENUMS(pre, val) pre##_NUM = (val),
  PREFIX_LIST(PREFIX_ENUMS)
};

#include <stdio.h>

int main (void)
{
  // one way to print
  #define prefix_to_val(pre) pre##_NUM
  printf("AAA_NUM: %d\n", prefix_to_val(AAA));
  printf("BBB_NUM: %d\n", prefix_to_val(BBB));

  // another alternative
  #define STR(s) #s  
  #define print_all_prefixes(pre, val) printf("%s: %d\n", STR(pre##_NUM), val);
  PREFIX_LIST(print_all_prefixes)
  
  return 0;
}

【讨论】:

    【解决方案2】:

    宏只在编译前处理,而不是在运行时处理。如您所见here,您的代码示例不起作用。

    良好做法(例如 MISRA 编码规则)建议尽可能少使用宏,因为它容易出错。

    【讨论】:

      【解决方案3】:

      预处理器在编译时工作,这里 name_aname_b 是非常数,即使它们是(即 const char *str 在 C++ 中是实常数,但在 C 中不是),也存在文字替换和预处理器不知道变量的内容。

      这行得通(注意参数应该被另一个宏扩展以获得有效的令牌):

      #include <stdio.h>
      
      #define AAA_NUM 10
      #define BBB_NUM 20
      
      #define _PREFIX_NUM(string) string##_NUM
      #define PREFIX_NUM(string) _PREFIX_NUM(string)
      
      int main(void)
      {
          #define name_a AAA
          #define name_b BBB
      
          printf("AAA_NUM: %d\n", PREFIX_NUM(name_a));
          printf("BBB_NUM: %d\n", PREFIX_NUM(name_b));
      
          return 0;
      }
      

      【讨论】:

        【解决方案4】:

        C 中没有办法创建运行时符号并使用它们。 C 是一种编译语言,所有符号都必须在编译之前知道。

        预处理器(在编译之前在文本级别进行更改)对 C 语言一无所知。

        【讨论】:

          猜你喜欢
          • 2013-01-11
          • 1970-01-01
          • 2017-01-14
          • 2016-04-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多