Toothpick Anemone
Toothpick Anemone

Reputation: 4644

How would we write a C macro to insert casts into function calls?

How might we write a preprocessor macro to replace every instance of:
func(
with
func((DemoUnion)?

Also, maybe a macro to replace func((DemoUnion)(DemoUnion) with func((DemoUnion)?

By the way, below is an example of how DemoUnion might be defined:

union DemoUnion {
    char c;
    short s;
    int i;
    float f;
}; typedef union DemoUnion DemoUnion;


// the typedef  allows us to declare instances by writing
//     DemoUnion instanceName;  
// instead of:
//     union DemoUnion instanceName;  

Also, C allows us to cast to union types pretty easily:
(so long as the input to the cast is one of the types included in the union)

int main() {
  DemoUnion big = 0;
  char c  = 1;
  big = (DemoUnion) c; // cast char to union type

  func(big);
  func((DemoUnion) c);
}

Upvotes: 1

Views: 969

Answers (2)

John Bollinger
John Bollinger

Reputation: 180181

How might we write a preprocessor macro to replace every instance of:

func(

with

func((DemoUnion)?

We wouldn't write such a macro, because C does not afford a way to do it. Macro expansion replaces the macro identifier and, for function-like macros, its argument list, with the macro's replacement text. The ( character cannot be part of a macro identifier, and it is not, by itself, an argument list. Thus, func( is not a unit that is subject to macro expansion.

You could, however, do this:

#define func(x) func((DemoUnion)(x))

That will have about the effect you describe, but it is specific to argument-list length. Also, you do not have to worry about recursive expansion; C specifies that it does not happen.

Also, maybe a macro to replace func((DemoUnion)(DemoUnion) with func((DemoUnion)

Nope. Macro replacement replaces macros, not general text patterns. Anyway, anywhere that a (DemoUnion) cast is valid, (DemoUnion)(DemoUnion) is also valid and equivalent.

But note well that you have a serious misconception:

Also, C allows us to cast to union types pretty easily: (so long as the input to the cast is one of the types included in the union)

On the contrary, C does not allow casting to or from union types. At all. Some compilers will accept such casts as an extension, but it is non-standard. The closest the (C2011) standard permits would involve using a compound literal:

DemoUnion u = (DemoUnion) { .c = c };

Note well that although part of the syntax for a compound literal resembles a cast operator, there is no cast there. But really, why do that, when you can just use an ordinary initializer:

DemoUnion u = { .c = c };

... or ordinary member assignment:

DemoUnion u;
u.c = c;

as the situation warrants.

Going the other way, of course, you should just use member selection:

char c2 = u.c;

Upvotes: 2

Michal Butterweck
Michal Butterweck

Reputation: 438

It is not possible to have define name with "(". However, you may use function macro:

#define FOO(X) FOO((DemoUnion) (X))

or with variable number of arguments:

#define FOO(...) FOO((DemoUnion) __VA_ARGS__)

Upvotes: 0

Related Questions