views:

223

answers:

3

Hi guys, I've got a tricky problem that I need some help with.

Currently, I have a file with about 100 #defines in it, from 1-100, and each with a unique string value.

Now I'm trying to print this value, but instead of the value, I want to print what the #define is. For example:

#define FIRST_VALUE 1
var = FIRST_VALUE;
printf("%s", var);

and I want the printf to print FIRST_VALUE, not 1.

Is there any way to do this in C? Or must I just write out 100+ case blocks inside a switch statement?

+12  A: 

You can use stringification to achieve what you are looking for:

  #define FIRST_MACRO
  #define MACRO_TO_STRING(x) #x

  #include <stdio.h>

  main() {
     printf("%s\n",  MACRO_TO_STRING(FIRST_MACRO));
  }

This program will output:

FIRST_MACRO
David Segonds
This is what I was getting at when I mentioned Windows Message Maps, which i believe use a similar mechanism.
Mystere Man
That doesn't really answer the original question, though. He wants to dynamically print the macro "name" based on the value of a variable.
Dave Costa
+1  A: 

After talking to one of my TA's at school, we've decided that the best way to do this would be to write an AWK script to process the header file and automatically generate all the case statements needed.

Thanks guys!

samoz
A: 

You can't do exactly what you want, since by the time the compiler gets the pre-processor output, the "ONE" token is long gone. However, if your goal is to write the list of constants once but generate both tokens and strings, then this can be done.

First, use a macro to build the constants as enums in a header file. File enums.h:

#ifndef ENUMS_H
#define ENUMS_H

#ifndef ENUM
#define ENUM(name,val) enum { name = val };
#endif

ENUM(ONE,1)
ENUM(TWO,2)
ENUM(THREE,3)

#endif /* ENUMS_H */

Second, redefine the macro in a .c file to create a string/integer mapping and include the .h file in the right place. File enums.c:

#include 
#include 

typedef struct {
        char *str;
        int val;
} DescriptiveEnum;

static DescriptiveEnum enums[] = {
#define ENUM(name,val) { #name, val },
#include "enums.h"
};
#define NUM_ENUMS (sizeof(enums)/sizeof(enums[0]))

char *enum_to_str(int val)
{
        int i;
        for (i=0;i<NUM_ENUMS;i++) {
                if (enums[i].val == val) return enums[i].str;
        }
        return "";
}

Now both the enum constants and the mapping function are available to callers. File main.c:

#include <stdio.h>
#include <stdlib.h>
#include "enums.h"

char *enum_to_str(int val);

int main(int argc, char *argv[])
{
        int val;

        val = ONE;

        printf("%d %s\n",val,enum_to_str(val));

        return EXIT_SUCCESS;
}
Randy Proctor