Where does this declaration come from: main _2a((argc,argv), int argc, char * argv[])

409 views Asked by At

I am migrating lots of Oracle Pro*C Code under HP-Unix to a Linux Environment.

In a program there is only such a main method defined:

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

I have never seen such a decalaration before - and haven't found anything with google. Anyhow, it works and from what I see is used as a main function.

Can anybody tell something about this?

Edit: Good hint - there is a macro definition:

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

Still makes no clear view (for me..)

2

There are 2 answers

4
Keith Thompson On BEST ANSWER

We just have to expand the macro. You can use gcc -E to invoke just the preprocessor; it will also expand all #include directives, so the output is going to be ugly.

But let's do it manually. The arguments to the macro are token sequences, not expressions.

The macro definition is:

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

and the invocation is:

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

The arguments are:

  • list --> (argc,argv)
  • a1 --> int argc
  • a2 --> char * argv[]

Performing the replacements gives us:

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

This would more commonly be written on multiple lines:

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

This is an old-style function declaration. It's still legal in all versions of C (up to and including the 2011 standard), but it's been officially obsolescent since 1989. The disadvantage of this old form is that it didn't communicate parameter information to callers, so a compiler couldn't warn you if you called a function with the wrong number of types of arguments.

I'll bet there's an alternate definition of the _a2 macro that expands to more modern definition that includes a prototype, something like:

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

With that macro definition, the definition of main instead expands to this:

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

So the _a2 macro (the "a" presumably stands for "argument") lets you write code that can expand either to an old-style function definition (for pre-ANSI compilers) or to a modern definition with a prototype.

A reasonable way to implement it would have been:

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

But since you're very unlikely to find a C compiler that doesn't support prototypes (they've been a standard feature of the language for a quarter of a century now), it would make more sense just to remove the macro altogether and just use modern style function declarations and definitions.

Also, the definition of main is missing the return type of int. Prior to the 1999 C standard, it was legal to omit the return type, under the "implicit int" rule. The 1999 standard dropped this rule and made an explicit return type mandatory. Most C compilers in their default mode still permit the return type to be omitted, perhaps with a warning, but there's no good reason to omit it.

4
Kijewski On

This macro is used to make K&R C-style function definition look more like "modern" C89 definitions.

Expanded the code reads:

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

Or with a better indentation:

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

Which is an ancient way to write:

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