0

I cannot find something similar to this.

#define ONE 1
#define TWO 2

int main()
{
   int x = ONE;
   printf("%s \n", x);
}
//the desirable output will be "ONE"

Now, I saw the other answers with the

#define PRINT(X) printf("%s \n", #x);

and I did not find how to use it to get what I want.

19
  • 1
    Aren't you defining ONE to be 1? So you could say x = ONE; and it would be the same as what you are doing right now? Commented Apr 18, 2017 at 18:43
  • 1
    What do you want to accomplish? How about reading the documentation of printf? If that does not help, maybe you miss some of the basics of the language. The code above invokes undefined behaviour, iow: it is not valid C. Commented Apr 18, 2017 at 18:44
  • 1
    //the excepted output will be "ONE" Are you sure about this? Did you try that? Commented Apr 18, 2017 at 18:44
  • 1
    What behavior do you want for int x=ONE + ONE;? Commented Apr 18, 2017 at 18:48
  • 1
    @Nati.E: As I assumed: you missed basics of C and programming in general. There is no connection between the macro ONE and the int variable. No offence. but please get a book about programming in general and C specifically. Commented Apr 18, 2017 at 19:23

2 Answers 2

5

There is no direct way to do this. The only information you have in your printf call is a variable x whose current value happens to be 1 (at run time), which happens to be the expansion of a macro whose name is ONE. There is no way for the compiler to figure out the name ONE from that information. There might be several different macros with the same definition, or there might not be any.

If you want to print the string ONE given the integer value 1, you're going to have to set up some kind of lookup table or function. For example:

const char *const names[] = { "ZERO", "ONE", "TWO", "THREE", "FOUR", /* etc. */ };
printf("%s\n", names[x]);

It would be entirely up to you to get the names right, so that for example 1 doesn't map to "THREE".

Sign up to request clarification or add additional context in comments.

2 Comments

thank you, great solution!! but to call that it make me work hard. the answer of @HolyBlackCat is better for me. THANK YOU!
I'd make the array const, too.
0

As @KeithThompson said, there is no easy way.

But there is a clever hack which does more or less what you ask for.

#define MY_ENUM_LIST \
    X( ONE   , 1 ) \
    X( TWO   , 2 ) \
    X( THREE , 3 )

#define X(name, value) name = value,
enum MyEnum {MY_ENUM_LIST};
#undef X

const char *my_enum_to_str(enum MyEnum e)
{
    switch (e)
    {
        #define X(name, value) case value: return #name;
        MY_ENUM_LIST
        #undef X
      default:
        return "<invalid>";
    }
}

int main()
{
    int x = ONE;
    printf("%d\n", x); // prints "1"
    printf("%s\n", my_enum_to_str(x)); // prints "ONE"

    return 0;
}

It has following advantages over the naïve lookup table:

  • No need to repeat enumerator names twice.
  • You can have any enumerator values, not only a contiguous range.
  • You can't accidentaly assign an incorrect name to an enumerator.

5 Comments

That is an awful approach.
@Olaf Please elaborate. Saying "awful approach" is not constructive at all. AFAIK it's the best existing solution. The only alternatives are simple lookup tables (which require duplicating enumerator names, often leading to bugs) and looking up enumerator values by their names at runtime, which is obviously slow. The only downside of this approach is that the syntax is pretty exotic.
@HolyBlackCat: Debugging, maintenance are two aspects.
@Olaf My point is that any other solution (apart from code generation, which would work nicely) would require one of the two things: 1. Duplicating names of those enumerators. And there is no way you will know that you've accidentaly desynchronized those lists, until you start to get weird name/value mismatches. Isn't it harder to maintain the two lists than only one?
2. Looking up enumerator values at runtime, using something like int get_value(const char *), which is not only slow, but also lacks compile-time detection of invalid names, which also makes debugging/maintaining harder. Thus, I'm very interested in seeing more elegant solutions.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.