2
votes

I have the following macro:

‎#define GTR(type) \‎
type type##_gtr(type a, type b) \‎
‎{ \‎
‎   return a > b ? a : b;\‎
‎}‎

I understand that it generates functions, but if GTR(unsigned int) expands outside main(), how do I call the generated function? _gtr(a, b) does not work...

3
By the way, void main() is not allowed by standard C. You should use int main() instead.hugomg

3 Answers

3
votes

GTR(unsigned) would expand to:

unsigned unsigned_gtr(unsigned a, unsigned b)
{
‎   return a > b ? a : b;
}‎

In that case, you should call unsigned_gtr(a, b).

GTR(unsigned int), however, would fail with a syntax error because you are having two separate tokens and the name of the function cannot be properly produced.

4
votes

You would have to write unsigned int_gtr(a,b) so it would not work for that type with the macro definition you have created.

The reason is that the preprocessor simply replaces the type parameter and joins it to the text after the ##.

You could do something like create a typedef for unisgned int so there were no spaces and then use that, e.g.:

typedef unsigned int uint;
GTR(uint)
...
uint_gtr(a,b)
3
votes

This:

type##_gtr

inside the macro is glueing together the value of the type argument with the text _gtr. This happens between the return type and the opening parenthesis of the argument list, i.e. this forms the name of the function.

So if you use GTR(unsigned int), you fail since the full function prototype ends up looking like this:

unsigned int unsigned int_gtr(unsigned int a, unsigned int b)

which is not syntactically correct. Basically, the macro has a weakness in that it assumes type names cannot contain spaces, which is not true in C.

If you use GTR(unsigned), though, you should call it as unsigned_gtr().