6

我正在将 HP-Unix 下的大量 Oracle Pro*C 代码迁移到 Linux 环境。

在一个程序中,只定义了这样一个 main 方法:

main _2a((argc,argv), int argc, char * argv[])
{
...
}

我以前从未见过这样的声明——也没有在谷歌上找到任何东西。无论如何,它可以工作,并且据我所见,它被用作主要功能。

任何人都可以谈谈这件事吗?

编辑:很好的提示 - 有一个宏定义:

 # define _2a(list,a1,a2)                 list a1;a2;

仍然没有清晰的观点(对我来说..)

4

2 回答 2

8

该宏用于使K&R C风格的函数定义看起来更像“现代”C89 定义。

展开代码如下:

main (argc,argv) int argc;char * argv[];
{
...
}

或者使用更好的缩进:

main(argc, argv)
    int argc;
    char *argv[];
{
    ...
}

这是一种古老的书写方式:

int main(int argc, char *argv[])
{
    ...
}
于 2014-11-18T15:45:12.050 回答
7

我们只需要扩展宏。您可以使用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”可能代表“argument”)让您编写的代码既可以扩展旧式函数定义(用于 ANSI 前编译器),也可以扩展为带有原型的现代定义。

实现它的合理方法是:

#ifdef __STDC__
#define _2a(list,a1,a2) (a1, a2) 
#else
#define _2a(list,a1,a2) list a1;a2;
#endif

但是由于您不太可能找到不支持原型的 C 编译器(它们已经成为该语言的标准特性已有 25 年了),因此完全删除宏和只需使用现代风格的函数声明和定义。

此外, 的定义main缺少 的返回类型int。在 1999 C 标准之前,根据“隐式int”规则,省略返回类型是合法的。1999 年的标准删除了这条规则,并强制要求明确的返回类型。大多数 C 编译器在其默认模式下仍然允许省略返回类型,可能带有警告,但没有充分的理由省略它。

于 2014-11-18T15:55:54.173 回答