简体   繁体   中英

Dynamically use a structure in c

In my code there are multiple structures like structure_1, structure_2, structure_3 etc. I am trying to write a macro which will enable me to select the correct structure (which structure to select is based on another value). I can't reveal the exact code...but its similar to this

#include <stdio.h>

#define concat(X,Y)     X##_##Y
#define typename(X){\
    if(val==0)\
        concat(X,1)\
    else\
        concat(X,2)\
}

int val;

typedef struct  {
    int x;
    char c;
}structure_1;

typedef struct  {
    int y;
    char c;
}structure_2;

int main()  {
    val = 0;
    typename(structure) abc;
    abc.x = 0;
    printf("%d\n",abc.x);
}

This doesn't work and is giving issues

24  11  E:\DEV\concat.c [Error] expected expression before 'structure_1'
3   22  E:\DEV\concat.c [Note] in definition of macro 'concat'
24  2   E:\DEV\concat.c [Note] in expansion of macro 'typename'
25  2   E:\DEV\concat.c [Error] 'abc' undeclared (first use in this function)
25  2   E:\DEV\concat.c [Note] each undeclared identifier is reported only once for each function it appears in

Using if-else statement is an option, but it'll have to be done for many structures and in many places, so i want to avoid that. Please suggest what i am doing wrong or any other way of doing it.

The reason your macro doesn't work is because it results in if (val == 0) structure_1; which won't compile because you haven't declared a variable. The abc part isn't injected into the macro, so it only appears at the end of the processed macro expansion: abc only gets declared as a variable of structure_2 .

This is easily enough fixed: you have to have the variable name as a parameter to your macro as well. Do that and... now the very point has obviously become ruined because your variables exist only inside the if-else blocks which is what you didn't want.

It's at this point that it should become obvious that this simply isn't how C works fundamentally. Genericism isn't well supported, which is a good thing because genericism isn't relevant to what C is trying to accomplish as a language. You should ask yourself why you are trying to force the language to behave this way. What is the point of what you are trying to do?

Regardless, there is a way to get around this in some sense: Unions. Unions allow you to essentially smack different types together into one type. This has the distinct drawback of forcing variables declared from a union to always be the size of the largest type. If you make a union from a 1-byte char and a 100-byte struct, every variable declared will always consume 100-bytes. On the other hand, if you are smacking together same-sized structs, there is no particular penalty.

A simple demonstration:

struct t {
    union {
        int x; float y;
    };
};
int main() {
    struct t a = {0};
    printf("%d\n", a.x);
    printf("%d\n", a.y);
    printf("%d\n", sizeof(a)); // 4
    return 0;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM