What's the point of a PROTOTYPE macro that merely expands to its arguments?

C++Macros

C++ Problem Overview


I have a header file which contains

#define PROTOTYPE(s) s

What is the point of that? Seems like it would just replace the input with itself.

There are TONS of other directives around it, but the only one that appears to have any bearing just checked if it's defined: #ifndef PROTOTYPE. I found some places in HDF4 header files that do this: #define PROTOTYPE. So, none of that really clear up my question. Still seems pretty useless.

Here's how it's used:

CS_RETCODE clientmsg_callback PROTOTYPE((
CS_CONTEXT * context,
CS_CONNECTION *connection,
CS_CLIENTMSG *clientmsg));

This is part of a project which uses Sybase Open Client. clientmsg_callback is later used here:

ct_callback(context, NULL, CS_SET, CS_CLIENTMSG_CB,
                  (CS_VOID *)clientmsg_callback);

I'm going off of a sample program from here:

http://infocenter.sybase.com/help/index.jsp?topic=/com.sybase.infocenter.dc35570.1570/html/clcprgde/clcprgde10.htm

clientmsg_callback is implemented later. I think the sample was originally written with C in mind, instead of C++. Perhaps that has something to do with it?

C++ Solutions


Solution 1 - C++

Back in the olden days of really, really early C, there was no such thing as a prototype. Function argument lists came after the function's parentheses, like this:

square(x)
int x;
{
int y = x * x;
return y;
}

These days, of course, the arguments go inside the parentheses:

square(int x)
{
int y = x * x;
return y;
}

Note the "missing" return type; C functions used to implicitly return int, and it was only if you needed a different return type that you had to say what it was.

Function declarations had yet another set of rules. A function declaration in K&R C (the ancient version) had no arguments:

int square();

And function prototypes in ANSI C have a list of arguments:

int square(int x);

During the transition, people used wacky macros so they could compile both ways:

int square(PROTOTYPE(int x));

With

#define PROTOTYPE(s)

that would expand to the first version.

With

#define PROTOTYPE(s) s

it would expand to the second.

With regard to the "extra" parentheses in the code in the question, they're needed when there is more than one argument in the argument list. Without them, the macro invocation has more than one argument, so won't match a macro defined with just one argument:

PROTOTYPE(int x, int y)   // error: too many arguments
PROTOTYPE((int x, int y)) // ok: only one argument (enclosed in parentheses)

Solution 2 - C++

Macros like this would be used in the prototypes in the header file to allow something like this:

int foo PROTOTYPE((int bar));

If ANSI C was detected (__STDC__ defined as 1), this would expand to:

int foo(int bar);

If ANSI C was not detected, this would expand to:

int foo();

which was common before C was standardized.

Some libraries still do this; if you look in tcpd.h (if you have it available), you'll see:

/* someone else may have defined this */
#undef  __P

/* use prototypes if we have an ANSI C compiler or are using C++ */
#if defined(__STDC__) || defined(__cplusplus)
#define __P(args)       args
#else
#define __P(args)       ()
#endif

This explains it well.

As for the double parentheses, __P(arg1, arg2) would give a syntax error (passing too many arguments to the macro), while __P((arg1, arg2)) would be fine (just one enclosed in parentheses).

This is similar to __extension__((...)) in GNU C. In non-GNU compilers, simply #define __extension__(unused) to have semi-portable code, as just one "argument" is given, wrapped in parentheses.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionCharlie ElversonView Question on Stackoverflow
Solution 1 - C++Pete BeckerView Answer on Stackoverflow
Solution 2 - C++S.S. AnneView Answer on Stackoverflow