0

I'm trying the code sequence below... my intent is to generate a new string that uses the input argument of the macro as a number and treats it as an int when it does concatenation. but looks like it's treating it as a string. Any way to accomplish this?

typedef enum
{
    HELLO0BYE = 0,
    HELLO1BYE = 1,
    HELLO2BYE = 2,
    HELLO3BYE = 3,
    HELLO4BYE = 4,
    HELLO5BYE = 5,

} enum_test;

#define GEN_NEW(x) HELLO ##x## BYE
void main()
{
    enum_test input = 5;
    enum_test output;
    output = GEN_NEW(input);
}

Ideally I want to be able to iterate through the enums in an algorithmic way.

KAM
  • 115
  • 1
  • 3
  • 5
  • 2
    `number` does not have a value on the preprocessing `stage`. It's just a token for a preprocessor. – Eugene Sh. May 30 '17 at 13:52
  • 1
    Can you add an example of the output you want? – simo-r May 30 '17 at 13:58
  • 1
    Note that `##` should appear between to identifier-like tokens in a macro expansion. The first `##` is erroneous. – Jonathan Leffler May 30 '17 at 13:58
  • 1
    Every time you are trying to do something like this, think: what code will be passed from the preprocessor to the compiler? Think like the preprocessor! – Eugene Sh. May 30 '17 at 14:07
  • I wonder what you are trying to achieve. Why not simply do `output = input;` ? – Support Ukraine May 30 '17 at 14:15
  • Probably not representing what i'm trying to actually do.. my original enum list is a lot larger (few hundred enums)... and amongst that large list I wan't to be able to select the enum based on input parameter. And it's not a 1:1 mapping either (input 0 doesn't equal 0 output). – KAM May 30 '17 at 15:09
  • 1
    @KAM In that case you should update your question to show the real problem. Anyway, as others have already said: macros are not a runtime tool. – Support Ukraine May 30 '17 at 15:23

3 Answers3

2

As I understand your question, no you can't. But I suspect I'm not entirely sure what you are trying to do.

Macro's are pre-processed. That means the macro's get substituted BEFORE your code gets compiled. So when you use the GEN_NEW macro, all the compiler knows about "number" is that it's a string. So you can't pass a run-time variable to a macro.

Hope that helps.

Richard
  • 113
  • 8
1

When above code is processed by compiler then, we get following output:

# 1 "Test1.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "Test1.c"
typedef enum
{
    HELLO0BYE = 0,
    HELLO1BYE = 1,
    HELLO2BYE = 2,
    HELLO3BYE = 3,
    HELLO4BYE = 4,
    HELLO5BYE = 5,

} enum_test;


void main()
{
    enum_test input = 5;
    enum_test output;
    output = HELLOinputBYE;
}

When you look at above code you can see that the following line is having error:

output = HELLOinputBYE;

Note: To stop the the compiler after preprocessing stage use '-E' switch. I used following on gcc compiler:

gcc -E -o TestPreprocessedFile.txt Test1.c

Here 'Test1.c' is source file and 'TestPreprocessedFile.txt' is output file.

For more about gcc compiler options refer Options Controlling the Kind of Output

cse
  • 4,066
  • 2
  • 20
  • 37
0

I don't know the exact logic of your implementation, so I won't go into that discussion. You can use this :

#define CONV2STRING(X) #X
#define TO_STRING(X) CONV2STRING(X)
#define EXPAND(Y) Y
#define MERGER( X, Y) X##Y
#define MERGE( X, Y) MERGER( X, Y)

#define SAY_HELLO HELLO
#define SAY_BYE BYE

typedef enum {
    HELLO0BYE = 0,
    HELLO1BYE = 1,
    HELLO2BYE = 2,
    HELLO3BYE = 3,
    HELLO4BYE = 4,
    HELLO5BYE = 5,
} enum_test;

const static struct {
    enum_test      value;
    const char *str;
} conversion [] = {
    {HELLO0BYE, "HELLO0BYE"},
    {HELLO1BYE, "HELLO1BYE"},
    {HELLO2BYE, "HELLO2BYE"},
    {HELLO3BYE, "HELLO3BYE"},
    {HELLO4BYE, "HELLO4BYE"},
    {HELLO5BYE, "HELLO5BYE"},
};

int StringToEnum (const char *str) {
     int j;
     for (j = 0;  j < sizeof (conversion) / sizeof (conversion[0]);  ++j)
         if (!strcmp (str, conversion[j].str))
             return conversion[j].value;
     return -1;
}

int main(int argc, char** argv)
{
    enum_test output;

    #define INPUT 5
    output = StringToEnum(TO_STRING (MERGE(MERGE( SAY_HELLO, EXPAND(INPUT)), SAY_BYE)));
    printf( "Macro Expansion : %s\n", TO_STRING (MERGE(MERGE( SAY_HELLO, EXPAND(INPUT)), SAY_BYE)));
    printf("output = %d\n", output);
    #undef INPUT

    #define INPUT 4
    output = StringToEnum(TO_STRING (MERGE(MERGE( SAY_HELLO, EXPAND(INPUT)), SAY_BYE)));
    printf( "Macro Expansion : %s\n", TO_STRING (MERGE(MERGE( SAY_HELLO, EXPAND(INPUT)), SAY_BYE)));
    printf("output = %d\n", output);
    #undef INPUT
}

Note: I found the elegant conversion from string to enum here.

Shuvam
  • 211
  • 2
  • 7