Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C function syntax, parameter types declared after parameter list

Tags:

c

syntax

function

I'm relatively new to C. I've come across a form of function syntax I've never seen before, where the parameter types are defined after that parameter list. Can someone explain to me how it is different than the typical C function syntax?

Example:

int main (argc, argv)
int argc;
char *argv[];
{
return(0);
}
like image 582
John Avatar asked Oct 18 '09 16:10

John


People also ask

What are the types of parameters used in C functions?

Parameters in C functions There are two ways to pass parameters in C: Pass by Value, Pass by Reference.

What are the 2 types of function parameters?

Parameter Types Presently, the type is one of ref, const, or val. The type indicates the relationship between the actual argument and the formal parameter. , for a full discussion of references.)

What are parameter and list down its types?

Answer :The parameter list of a function describes the number and types of the arguments that the function accepts, and the number and types of the values it returns. ... It may also specify that calls to the generic function may contain any keyword arguments.

How many types of parameters are in a function?

We can use all 4 types of parameters in one function.


2 Answers

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

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

would be the same function.

like image 148
Ferruccio Avatar answered Oct 18 '22 21:10

Ferruccio


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

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

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

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

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

}

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

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

Your options of 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 2 should be preferred if you have the choice because it gets rid of the old style definition up front. If such contradicting function types for a function appears in the same translation unit, the compiler will usually tell you (but is not required). If such contradictions appear over multiple translation units, the error will possibly go unnoticed and can result in hard to predict bugs. It is best to avoid these old style definitions.

like image 29
Johannes Schaub - litb Avatar answered Oct 18 '22 19:10

Johannes Schaub - litb