5

I am coming from a C++ background, and have recently taken up C. I am am having trouble assigning a number to a type (or vice versa); what I need is some way to assign a unique ID to a type, preferably starting from 0. My goal is to have a function (or macro) that indexes an array based on a passed-in type, which I believe to only be achievable through macros.

Also, since I use the sizeof() the type which I need to be passed in, it makes using enums as an alternative difficult. If I were to pass the enumerator to the function/macro instead, then I would have to get the type from the number, the exact opposite (but maybe easier) problem.

Is this even possible in C? I have tried researching this question, but have not found any answer to this problem particularly, which I was able to do in C++ with templates, like so:

int curTypeIdx = 0;

template <typename T>
struct TypeHandle {
    static int const val;
}

template <typename T>
int const TypeHandle<T>::val = curTypeIdx++;

The reason for this is that I am building an ECS. I have an EntityManager struct, which is supposed to contain arrays of components. Since I plan for this to be general-purpose, I defined an upper limit of components (MAX_COMPONENTS) and have an array of char*s of length MAX_COMPONENTS. At a basic level, The goal is to give the user of the EntityManager the ability to define their own components, and store them in these generic arrays.

If there is any other way to

Thank you all for any advice.

mrFoobles
  • 149
  • 2
  • 9
  • Why not use an `enum`? – emsimpson92 Aug 17 '18 at 21:49
  • The macro also uses the sizeof that type for casting, so if I use an enum I would have to do the opposite: get a type from a number index. I'll edit the original post to clarify. – mrFoobles Aug 17 '18 at 21:53
  • 4
    What do you mean by "assign a number to a type"? Can you maybe show an example of how you would do that in C++? – mkrieger1 Aug 17 '18 at 21:53
  • I edited the post to demonstrate a simplified but working solution. – mrFoobles Aug 17 '18 at 21:58
  • 1
    you could define your types in the same file, and use `__LINE__` (current line number) as the unique ID. can you show us what you want to achieve in C? – Jean-François Fabre Aug 17 '18 at 22:04
  • Can you show what you *actually* want to do ("function that indexes array based on type")? Maybe your approach isn't quite the way to go. (Otherwise, is this what you want to do? https://stackoverflow.com/questions/479207/how-to-achieve-function-overloading-in-c) – mkrieger1 Aug 17 '18 at 22:07
  • No as the C types do not have constructors. @Jean-FrançoisFabre there is a difference between compile and run time type number. – 0___________ Aug 17 '18 at 22:07
  • 5
    This sounds like an [XY problem](https://en.wikipedia.org/wiki/XY_problem). You are trying to solve problem X and have solution Y in your head that is incomplete. You are now asking a question about Y when there is likely another solution Z to your problem that better fits with the tools available in the C language. Please provide more information about the original problem X that you are trying to solve. – Code-Apprentice Aug 17 '18 at 22:18
  • Thanks, I tried to edit the post to give a more general idea of what I want to do, in case there is a better way. – mrFoobles Aug 17 '18 at 22:31
  • I just looked back at my old code and saw that I defined the value outside of the class. Is it still invalid/undefined behavior? It worked fine with my old project. – mrFoobles Aug 17 '18 at 22:46
  • How portable does the code have to be? Can you use something GCC specific? – jxh Aug 17 '18 at 23:11
  • I am using GCC, so that would be fine. – mrFoobles Aug 17 '18 at 23:11
  • @mrFoobles: Consider using the [constructor function attribute](https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#Common-Function-Attributes). – jxh Aug 17 '18 at 23:18

1 Answers1

4

If you are OK with enumerating ALL supported types once( and update the list if language comes up with new types), then you can use the stringize functionality of C macros and an array of strings to achieve what you want.

#define GET_TYPE_ID(type) get_type_id(#type)
const char *type_strings[] = { "char", "unsigned char", "short" /* so on.. */};

int get_type_id(const char* type_string) {
    for( int i = 0; i < sizeof(type_strings)/sizeof(const char*); i++) {
         if ( strcmp(type_string, type_strings[i]) == 0 ) return i;
    }
    // Should never reach here if you have taken care of all types and 
    // don't pass in illegal types.
}

Now you can get an integer ID for each type with GET_TYPE_ID(int), GET_TYPE_ID(char) and so on.

Pavan Manjunath
  • 27,404
  • 12
  • 99
  • 125
  • Thanks! I had no idea about the `#` capability of macros. I could use that to make some sort of "register type" macro. – mrFoobles Aug 17 '18 at 22:59