KAM
KAM

Reputation: 117

Argument to macro not being substituted correctly in C

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.

Upvotes: 0

Views: 216

Answers (3)

Shuvam
Shuvam

Reputation: 211

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.

Upvotes: 0

cse
cse

Reputation: 4104

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

Upvotes: 1

Richard
Richard

Reputation: 113

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.

Upvotes: 2

Related Questions