Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
102 views
in Technique[技术] by (71.8m points)

How do I check if a variable is of a certain type (compare two types) in C?

In C (not C++/C#) how do I check if a variable is of a certain type?

For example, something like this:

double doubleVar;
if( typeof(doubleVar) == double ) {
    printf("doubleVar is of type double!");
}

Or more general: How do I compare two types so that compare(double1,double2) will evaluate to true, and compare(int,double) will evaluate to false. Also I'd like to compare structs of different composition as well.

Basically, I have a function that operates on variables of type "struct a" and "struct b". I want to do one thing with the "struct a" variables and the other with the "struct b" variables. Since C doesn't support overloading and the void pointer losses its type information I need to check for type. BTW, what would be the sense in having a typeof operator, if you can't compare types?


The sizeof method seems to be a practical workaround solution for me. Thanks for your help. I still find it a bit strange since the types are known at compile time, but if I imagine the processes in the machine I can see, why the information is not stored in terms of types, but rather in terms of byte size. Size is the only thing really relevant besides addresses.

Question&Answers:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Getting the type of a variable is, as of now, possible in C11 with the _Generic generic selection. It works at compile-time.

The syntax is a bit like that for switch. Here's a sample (from this answer):

    #define typename(x) _Generic((x),                                                 
            _Bool: "_Bool",                  unsigned char: "unsigned char",          
             char: "char",                     signed char: "signed char",            
        short int: "short int",         unsigned short int: "unsigned short int",     
              int: "int",                     unsigned int: "unsigned int",           
         long int: "long int",           unsigned long int: "unsigned long int",      
    long long int: "long long int", unsigned long long int: "unsigned long long int", 
            float: "float",                         double: "double",                 
      long double: "long double",                   char *: "pointer to char",        
           void *: "pointer to void",                int *: "pointer to int",         
          default: "other")

To actually use it for compile-time manual type checking, you can define an enum with all of the types you expect, something like this:

    enum t_typename {
        TYPENAME_BOOL,
        TYPENAME_UNSIGNED_CHAR,
        TYPENAME_CHAR,
        TYPENAME_SIGNED_CHAR,
        TYPENAME_SHORT_INT,
        TYPENAME_UNSIGNED_CHORT_INT,
        TYPENAME_INT,
        /* ... */
        TYPENAME_POINTER_TO_INT,
        TYPENAME_OTHER
    };

And then use _Generic to match types to this enum:

    #define typename(x) _Generic((x),                                                       
            _Bool: TYPENAME_BOOL,           unsigned char: TYPENAME_UNSIGNED_CHAR,          
             char: TYPENAME_CHAR,             signed char: TYPENAME_SIGNED_CHAR,            
        short int: TYPENAME_SHORT_INT, unsigned short int: TYPENAME_UNSIGNED_SHORT_INT,     
              int: TYPENAME_INT,                     
        /* ... */                                    
            int *: TYPENAME_POINTER_TO_INT,          
          default: TYPENAME_OTHER)

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...