Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Checking if a type is a struct or pointer at compile time in C?

NOTE: This is NOT a duplicate of the question linked by Paul T, because I am asking if it is possible to determine if a type is of a certain broader incomplete type/kind at compile time, not if a symbol has been registered at compile time. This seems like a fundamental misunderstanding of the question.

I am writing a library in C that deals with pseudo-generic functions which take a type as an argument through a macro wrapper.

To spare the details (because they are rather complicated) there are two possible features that could help, I think:

  • Being able to detect if a type is a pointer at compile time. (No, the "use _Generic to test if you get ptrdiff_t from subtraction" trick won't work, because structures are a possibility, and you can't subtract structures.)

  • Being able to detect if a type is a struct at compile time. (If this was possible, then the aforementioned _Generic trick could be used if the type was detected as not being a struct.)

I've tried everything I could think of on Godbolt (even trying to compare types to incomplete anonymous structs and toying with __builtin_types_compatible_p) and wasn't able to find any solutions.

If anyone has any solutions I'd love to see them, otherwise I may just end up having to complicate the design a bit-- so not the end of the world if it's impossible, but it would be ideal if it can be done.

To give a basic idea of what one of these macros might look like or their expected output:

int *a;
assert(!IS_STRUCT(a));
assert(IS_POINTER(a));
struct {} b;
assert(IS_STRUCT(b));
assert(!IS_POINTER(b));

shouldn't throw any errors.

like image 658
k1tt3hk4t Destroyer of Fish Avatar asked Oct 23 '25 17:10

k1tt3hk4t Destroyer of Fish


1 Answers

Complete Answer (if EDG Front End used):

If your IDE / compiler is using the EDG C++ Front End (which a lot are), and you are using C, not C++ (which your tag suggests), and you say you ARE using typeof, then you can detect a structs as follows (see the latest manual, page 75):

/* Test if EDG Front End is used*/
#if defined(__EDG__) && defined(__EDG_VERSION__)
#define IS_STRUCT(expression_or_type_name) __is_class(typeof (expression_or_type_name)))
#endif

since in C __is_class() will only be true for a struct (http://www.cplusplus.com/reference/type_traits/is_class/).

Further, pointers can similarly be detected as follows:

/* Test if EDG Front End is used*/
#if defined(__EDG__) && defined(__EDG_VERSION__)
#define IS_POINTER(expression_or_type_name) (__is_convertible_to(typeof (expression_or_type_name), void*) || __is_convertible_to(typeof (expression_or_type_name), void const*) || __is_convertible_to(typeof (expression_or_type_name), void volatile*) || __is_convertible_to(typeof (expression_or_type_name), void const volatile*))
#endif

(http://www.cplusplus.com/reference/type_traits/is_convertible/)

like image 186
Gunther Schulz Avatar answered Oct 26 '25 08:10

Gunther Schulz