[ACCEPTED]-C function syntax, parameter types declared after parameter list-function

Accepted answer
Score: 72

That's the old-style syntax for parameter 4 lists, which is still supported. In K&R 3 C you could also leave off the type declarations 2 and they would default to int. i.e.

main(argc, argv)
char *argv[];
{
    return 0;
}

would 1 be the same function.

Score: 29

What's also interesting is the calling convention 37 difference of functions with, and functions 36 without a prototype. Consider an old style 35 definition:

void f(a)
 float a; {
 /* ... */
}

In this case, the calling convention 34 is that all arguments are promoted before 33 being passed to the function (for example, a 32 float argument is first promoted to double, before 31 being passed). So if f receives a double but the 30 parameter has type float (which is perfectly 29 valid) the compiler has to emit code that 28 converts the double to a float prior to 27 executing the function's body.

If you include 26 a prototype, the compiler does not do such 25 automatic promotions anymore and any data 24 passed is converted to the types of the 23 parameters of the prototype as if by assignment. So 22 the following is not legal and results in 21 undefined behavior:

void f(float a);
void f(a)
  float a; {

}

In this case, the function's 20 definition would convert the submitted parameter 19 from double (the promoted form) to float because the 18 definition is old-style. But the parameter 17 was submitted as a float, because the function 16 has a prototype. For example, clang gives

main.c:3:9: warning: promoted 15 type 'double' of K&R function parameter 14 is not compatible with the parameter type 13 'float' declared in a previous prototype 12 [-Wknr-promoted-parameter]

Your options of 11 solving the contradictions are the two following:

// option 1
void f(double a);
void f(a)
  float a; {

}

// option 2
// this declaration can be put in a header, but is redundant in this case, 
// since the definition exposes a prototype already if both appear in a 
// translation unit prior to the call. 
void f(float a); 

void f(float a) {

}

Option 10 2 should be preferred if you have the choice 9 because it gets rid of the old style definition 8 up front. If such contradicting function 7 types for a function appears in the same 6 translation unit, the compiler will usually 5 tell you (but is not required). If such 4 contradictions appear over multiple translation 3 units, the error will possibly go unnoticed 2 and can result in hard to predict bugs. It 1 is best to avoid these old style definitions.

Score: 11

This is the so caller K&R style or old-style declaration.

Note, that 5 this declaration is significantly different from the 4 modern declaration. K&R declaration 3 does not introduce a prototype for the function, meaning 2 that it doesn't expose the types of the 1 parameters to the outside code.

Score: 7

There is no difference, it is just that 3 that is the old syntax for function declarations 2 in C -- it was used pre ANSI. Never write such code unless you plan to give it to your friends from the 80's. Also, never depend upon implicit type assumptions (as 1 another answer seems to suggest)

Score: 5

While the old syntax for function definition 6 still works (with warnings, if you ask your 5 compiler), using them does not provide function 4 prototypes.
Without function prototypes 3 the compiler will not check if the functions 2 are called correctly.

#include <stdio.h>
int foo(c)
int c;
{ return printf("%d\n", c); }

int bar(x)
double x;
{ return printf("%f\n", x); }

int main(void)
{
    foo(42); /* ok */
    bar(42); /* oops ... 42 here is an `int`, but `bar()` "expects" a `double` */
    return 0;
}

When the program is 1 run, the output on my machine is

$ gcc proto.c
$ gcc -Wstrict-prototypes proto.c
proto.c:4: warning: function declaration isn’t a prototype
proto.c:10: warning: function declaration isn’t a prototype
$ ./a.out
42
0.000000
Score: 1

Its just the same but old fashion. You probably 1 found it is some old, legacy code.

Score: 0

Old or not, I would argue what is old and 16 what not.. like the pyramids are ancient, but 15 none of today’s so-called scientists have 14 a clue how they were made. Looking back, old 13 programs still work today without memory 12 leaks, but these "new" programs 11 tend to fail more than often. I see a trend 10 here.

Probably they saw functions as structs 9 which have an executable body. Knowledge 8 of ASM is needed here to solve the mystery.

Edit, found 7 a macro which indicates you do not need 6 to supply argument names at all.

#ifndef OF /* function prototypes */
#  ifdef STDC
#    define OF(args)  args
#  else
#    define OF(args)  ()
#  endif
#endif

#ifndef Z_ARG /* function prototypes for stdarg */
#  if defined(STDC) || defined(Z_HAVE_STDARG_H)
#    define Z_ARG(args)  args
#  else
#    define Z_ARG(args)  ()
#  endif
#endif

Here is 5 an usage example, library is zlib-1.2.11.

ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));

So my second 4 guess would be for function overloading, otherwise 3 these arguments had no use. One concrete 2 function, and now infinite amount of functions 1 with same name.

More Related questions