Search code examples
cpointersvoid-pointers

C getting type of a pointer


I want to implement a function that takes either int or a char pointer as the input and stores then as a void pointer but I also want to store the type of the pointer that has been passed so is there a way that I could find the type of the pointer


Solution

  • You can perform sort-of-overloading on types using _Generic macro if you are using a C11 compliant compiler, but the type has to be stored separately, be it a void* or an union with some sort of tag.

    The closest to what you want is sth like this:

    #include <stdio.h>
    #include <assert.h>
    
    struct TaggedUnion
    {
        void* contents;
        /* union {int* i;char* c;} contents; */
    
        enum Type {CHAR_TYPE, INT_TYPE} type;
    };
    
    struct TaggedUnion storeI(int* x)
    {
        struct TaggedUnion ret = {.contents =x, .type=INT_TYPE};
        return ret;
    }
    
    struct TaggedUnion storeC(char* x)
    {
        struct TaggedUnion ret = {.contents =x, .type=CHAR_TYPE};
        return ret;
    }
    
    #define storeTagged(x) _Generic((x),\
        int*: storeI,\
        char*: storeC)(x)
    
    int* getInt(const struct TaggedUnion x)
    {
        return x.type == INT_TYPE ? x.contents : NULL;
    } 
    
    char* getChar(const struct TaggedUnion x)
    {
        return x.type == CHAR_TYPE ? x.contents : NULL;
    } 
    
    void fi(int* arg)
    {
        printf("i\n");
    }
    
    void fc(char* arg)
    {
        printf("c\n");
    }
    
    
    #define ff(x) _Generic((x),\
        int*: fi,\
        char*: fc)(x)
    
    int main(int argc, const char* argv[])
    {
        printf("entry\n");
        int* i;
        char* c;
    
        ff(i);
        ff(c);
    
        struct TaggedUnion ti = storeTagged(i);
        struct TaggedUnion tc = storeTagged(c);
    
        assert(ti.type == INT_TYPE);
        assert(tc.type == CHAR_TYPE);
    
        return 0;
    }
    

    https://godbolt.org/z/5dcrc84fo