问题
I am trying to write a macro to assist with object oriented programming in C. As I store the class information in a constant struct, I need to create a macro that does the following:
- Take the type of the object (typeof the derefenced pointer)
- Append
_info
to get the name of the desired classInfo struct - Take the address of that symbol so it can be passed to the function
- Call the
destroyObject
function with a pointer to the class struct and the object itself
An example:
queue_t* p = NULL;
delete(p);
delete
should expand to:
destroyObject(&(queue_t_info), p);
I tried using this macro, but I can't get to to work:
#define delete(X) (destroyObject(&(typeof(*X)##_info), X))
I'm having trouble with the typeof part to work correctly.
回答1:
typeof
isn't macro, it is language construction and it is expanded by compiler, not preprocessor. Since preprocessing goes before compilation, macro can't access typeof
result.
Your delete(p)
is expanded to: (destroyObject(&(typeof(*p)_info), p))
. (You can see it by -E
gcc flag)
回答2:
I realized that what I was attempting to do was impossible - the C preprocessor doesn't parse and symbolize the code so it doesn't know which type a variable is.
To solve this, I require the type to be passed into the delete function as well. This isn't ideal as it introduces a frequent source of bugs due to mismatched types. If a programmer passes a pointer to object A but specifies object B in the delete function, the wrong destructor would be called. To solve this, I added a typecheck to the macro so that a compiler warning would be generated for any mismatched types.
#define typecheck(type,x) \
({ type __dummy; \
typeof(x) __dummy2; \
(void)(&__dummy == &__dummy2); \
})
#define delete(P, X) (destroyObject(&(X##_info), P), typecheck(X, *P))
#define new(X, ...) (createObject(&(X##_info), ##__VA_ARGS__))
Normal usage of the macro:
queue_t* p = new(queue_t);
delete(p, queue_t);
However using the wrong type:
queue_t* p = new(queue_t);
delete(p, int);
causes a compiler warning:
Comparison of distinct pointer types ('int *' and 'typeof (*p) *' (aka 'queue_t *'))
来源:https://stackoverflow.com/questions/15086794/c-macro-get-typeof-argument