Home > Enterprise >  How to pass string as prefix of defined macro
How to pass string as prefix of defined macro

Time:09-24

Is there any idea to pass C string as part of the defined macro like below code?

#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;
}

Expected output

AAA_NUM: 10
BBB_NUM: 20

CodePudding user response:

As mentioned in other posts, you can't use run-time variables in the pre-processor. You could however create enum that way. Though it is usually not a good idea to generate identifiers with macros either, save for special cases like when maintaining an existing code base and you are limited in how much of the existing code you can/want to change. So it should be used as a last resort only.

The least bad way to write such macros would be by using a common design pattern called "X macros". These are used when it is important that code repetition should be reduced to a single place in the project. They tend to make the code look rather alien though... Example:

#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;
}

CodePudding user response:

A macro is only processed before compilation and not at runtime. Your code example does not work as you can see here.

Good practice (for example MISRA coding rules) recommend to use macros as little as possible since it is error prone.

CodePudding user response:

Preprocessor works at compile time and here name_a and name_b are non constant, and even if they were (i.e. const char *str is a real constant in C but not in C), there is a literal substitution and the preprocessor does not know the contents of variables.

This works (notice that the parameter should be expanded by another macro in order to get a valid token):

#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;
}

CodePudding user response:

There is no way in C to create runtime symbols and use them. C is a compiled language and all symbols have to be known before the compilation.

The preprocessor (which do changes on the text level before the compilation) does not know anything about the C language.

  • Related