仅扩展其参数的 PROTOTYPE 宏有什么意义?
What's the point of a PROTOTYPE macro that merely expands to its arguments?
我有一个头文件,其中包含
#define PROTOTYPE(s) s
这样做有什么意义?似乎它只会用自己替换输入。
它周围有大量其他指令,但唯一似乎有任何意义的指令只是检查它是否已定义:#ifndef PROTOTYPE
。我在 HDF4 头文件中找到了一些这样做的地方:#define PROTOTYPE
。所以,none 确实解决了我的问题。好像还是很没用。
使用方法如下:
CS_RETCODE clientmsg_callback PROTOTYPE((
CS_CONTEXT * context,
CS_CONNECTION *connection,
CS_CLIENTMSG *clientmsg));
这是使用 Sybase Open Client 的项目的一部分。 clientmsg_callback后面这里用到:
ct_callback(context, NULL, CS_SET, CS_CLIENTMSG_CB,
(CS_VOID *)clientmsg_callback);
我要从这里开始一个示例程序:
clientmsg_callback稍后实现。我认为示例最初是用 C 编写的,而不是 C++。也许这与它有关?
在非常非常早的 C 时代,还没有原型这样的东西。函数参数列表在函数的括号之后,like this:
square(x)
int x;
{
int y = x * x;
return y;
}
这些天,当然,参数放在括号内:
square(int x)
{
int y = x * x;
return y;
}
注意 "missing" return 类型; C 函数过去常常隐式 return int
,只有当您需要不同的 return 类型时,您才必须说出它是什么。
函数声明还有另一套规则。 K&R C(旧版本)中的函数声明没有参数:
int square();
ANSI C 中的函数 prototypes 有一个参数列表:
int square(int x);
在转换期间,人们使用了古怪的宏,以便他们可以两种方式进行编译:
int square(PROTOTYPE(int x));
有
#define PROTOTYPE(s)
这将扩展到第一个版本。
有
#define PROTOTYPE(s) s
它会扩展到秒。
关于问题代码中的"extra"括号,当参数列表中有多个参数时需要它们。没有它们,宏调用有多个参数,因此不会匹配仅用一个参数定义的宏:
PROTOTYPE(int x, int y) // error: too many arguments
PROTOTYPE((int x, int y)) // ok: only one argument (enclosed in parentheses)
像这样的宏将用于头文件中的原型以允许这样的事情:
int foo PROTOTYPE((int bar));
如果检测到 ANSI C(__STDC__
定义为 1),这将扩展为:
int foo(int bar);
如果未检测到 ANSI C,这将扩展为:
int foo();
这在 C 标准化之前很常见。
一些图书馆仍然这样做;如果您查看 tcpd.h
(如果可用),您会看到:
/* 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
这个解释的很好。
至于双括号,__P(arg1, arg2)
会给出语法错误(将太多参数传递给宏),而 __P((arg1, arg2))
会很好(只用括号括起来一个)。
这类似于 GNU C 中的 __extension__((...))
。在非 GNU 编译器中,只需 #define __extension__(unused)
即可获得半可移植代码,因为只给出一个 "argument",包装在括号。
我有一个头文件,其中包含
#define PROTOTYPE(s) s
这样做有什么意义?似乎它只会用自己替换输入。
它周围有大量其他指令,但唯一似乎有任何意义的指令只是检查它是否已定义:#ifndef PROTOTYPE
。我在 HDF4 头文件中找到了一些这样做的地方:#define PROTOTYPE
。所以,none 确实解决了我的问题。好像还是很没用。
使用方法如下:
CS_RETCODE clientmsg_callback PROTOTYPE((
CS_CONTEXT * context,
CS_CONNECTION *connection,
CS_CLIENTMSG *clientmsg));
这是使用 Sybase Open Client 的项目的一部分。 clientmsg_callback后面这里用到:
ct_callback(context, NULL, CS_SET, CS_CLIENTMSG_CB,
(CS_VOID *)clientmsg_callback);
我要从这里开始一个示例程序:
clientmsg_callback稍后实现。我认为示例最初是用 C 编写的,而不是 C++。也许这与它有关?
在非常非常早的 C 时代,还没有原型这样的东西。函数参数列表在函数的括号之后,like this:
square(x)
int x;
{
int y = x * x;
return y;
}
这些天,当然,参数放在括号内:
square(int x)
{
int y = x * x;
return y;
}
注意 "missing" return 类型; C 函数过去常常隐式 return int
,只有当您需要不同的 return 类型时,您才必须说出它是什么。
函数声明还有另一套规则。 K&R C(旧版本)中的函数声明没有参数:
int square();
ANSI C 中的函数 prototypes 有一个参数列表:
int square(int x);
在转换期间,人们使用了古怪的宏,以便他们可以两种方式进行编译:
int square(PROTOTYPE(int x));
有
#define PROTOTYPE(s)
这将扩展到第一个版本。
有
#define PROTOTYPE(s) s
它会扩展到秒。
关于问题代码中的"extra"括号,当参数列表中有多个参数时需要它们。没有它们,宏调用有多个参数,因此不会匹配仅用一个参数定义的宏:
PROTOTYPE(int x, int y) // error: too many arguments
PROTOTYPE((int x, int y)) // ok: only one argument (enclosed in parentheses)
像这样的宏将用于头文件中的原型以允许这样的事情:
int foo PROTOTYPE((int bar));
如果检测到 ANSI C(__STDC__
定义为 1),这将扩展为:
int foo(int bar);
如果未检测到 ANSI C,这将扩展为:
int foo();
这在 C 标准化之前很常见。
一些图书馆仍然这样做;如果您查看 tcpd.h
(如果可用),您会看到:
/* 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
这个解释的很好。
至于双括号,__P(arg1, arg2)
会给出语法错误(将太多参数传递给宏),而 __P((arg1, arg2))
会很好(只用括号括起来一个)。
这类似于 GNU C 中的 __extension__((...))
。在非 GNU 编译器中,只需 #define __extension__(unused)
即可获得半可移植代码,因为只给出一个 "argument",包装在括号。