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)