For example,
struct node {
struct node *left, *right;
};
#define LEFT(X) (X->left)
#define RIGHT(X) (X->right)
I would like to forbid macro call like this without changing the existing macro interface.
LEFT(n) = ...
Any idea?
The speed at which macros and functions differs. Macros are typically faster than functions as they don't involve actual function call overhead.
A macro is a fragment of code that is given a name. You can define a macro in C using the #define preprocessor directive. Here's an example. Here, when we use c in our program, it is replaced with 299792458 .
In C, the macro is used to define any constant value or any variable with its value in the entire program that will be replaced by this macro name, where macro contains the set of code that will be called when the macro name is used in the program.
Speed versus size The main benefit of using macros is faster execution time. During preprocessing, a macro is expanded (replaced by its definition) inline each time it is used. A function definition occurs only once regardless of how many times it is called.
Try this:
#define LEFT(X) ((X)->left+0)
#define RIGHT(X) ((X)->right+0)
#undef LEFT
#undef RIGHT
//template<class T>
inline const node * const LEFT(const node * X) {
return X->left;
}
I'd go with the inline function, but if you want a macro:
#define LEFT(X) (1 ? (X)->left : 0)
I don't think there is any way of preventing that. Probably the best way would be not to use macros.
You can use the ternary operator to force the result of the macro to be an rvalue, but the error message might be confusing to users:
struct node {
node *left, *right;
};
#define LEFT( x ) ( true ? (x).left : (node*)0 )
int main() {
node n;
// LEFT( n ); // error
node *l = LEFT( n ); // OK
}
The trickery there is in the semantics of that specific operator. The type of the expression containing just the operator is a common type (or a type convertible from) of the two branches of the expression, even if only one of them is ever evaluated. Now, when the compiler evaluates true ? x.left : (node*)0
it resolves to the expression x.left
but with the common type of x.left
and (node*)0
. Both of them are basically the same type, with the only detail that (node*)0
is an rvalue, rather than a lvalue.
Maybe const
, though it requires an explicit type:
#define LEFT(X) ((const struct node *) (X->left))
...though if you have the typeof
compiler extension:
#define LEFT(X) ((const typeof(X->left)) (X->left))
For C++, I would use unary +:
#define LEFT(X) (+((X)->left))
#define RIGHT(X) (+((X)->right))
For a general macro case, this has the advantage over adding +0
that it also works for void*
and function pointers. For C, you can use the comma operator
#define LEFT(X) (0, ((X)->left))
#define RIGHT(X) (0, ((X)->right))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With