我们只需要扩展宏。您可以使用
gcc -E
来调用预处理器;它还会展开所有的
#include
指令,因此输出将会很丑。
但是让我们手动操作。宏的参数是标记序列,而不是表达式。
宏定义如下:
# define _2a(list,a1,a2) list a1;a2;
调用方式如下:
main _2a((argc,argv), int argc, char * argv[])
{
...
}
参数如下:
list
--> (argc,argv)
a1
--> int argc
a2
--> char * argv[]
进行替换后,我们得到:
main (argc,argv) int argc; char * argv[];
{
...
}
这通常会写成多行:
main(argc, argv)
int argc;
char *argv[];
{
...
}
这是一种旧式的函数声明方式。虽然在所有版本的C中(包括2011标准)仍然合法,但自1989年以来就已经被正式弃用。这种旧式形式的缺点在于它没有向调用者传递参数信息,因此编译器无法警告您如果使用了错误数量或类型的参数来调用函数。我敢打赌,
_a2
宏的另一种定义会扩展成更现代的定义,其中包含原型,例如:
#define _2a(list,a1,a2) (a1, a2)
使用这个宏定义,
main
的定义会被扩展成以下内容:
main (int argc, char * argv[])
{
...
}
因此,_a2
宏(“a”可能代表“参数”)使您可以编写能够扩展为旧式函数定义(适用于ANSI之前的编译器)或具有原型的现代定义的代码。
实现它的一个合理方法是:
#ifdef __STDC__
#define _2a(list,a1,a2) (a1, a2)
#else
#define _2a(list,a1,a2) list a1
#endif
但是由于你几乎不可能找到一个不支持原型的C编译器(它们已经成为这门语言的标准特性超过了四分之一世纪),所以更有意义的做法就是完全删除宏,只使用现代风格的函数声明和定义。
此外,main
的定义缺少返回类型int
。在1999年C标准之前,可以根据"隐式int
"规则省略返回类型。1999年的标准取消了这个规则,并使显式返回类型成为必需。大多数C编译器在默认模式下仍然允许省略返回类型,可能会发出警告,但没有理由省略它。
_2a
是一个宏。 - Jabberwocky