Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Declaring parameters outside the declarator

Tags:

c

function

The C standard states that, for a function definition, if the declarator includes an identifier list, the types of the parameters shall be declared in a following declaration list. Apparently this makes a difference.

extern int max(int a, int b)
{
return a > b ? a : b;
}

extern int max(a, b)
int a, b;
{
return a > b ? a : b;
}

Here int a, b; is the declaration list for the parameters. The difference between these two definitions is that the first form acts as a prototype declaration that forces conversion of the arguments of subsequent calls to the function, whereas the second form does not.

What does this mean for the programmer and does it affect the code the compiler produces?

like image 586
someguy Avatar asked Jan 22 '12 13:01

someguy


People also ask

How do you declare a parameter in a function?

In a function declaration, or prototype, the type of each parameter must be specified. In the function definition, the type of each parameter must also be specified. In the function definition, if the type of a parameter is not specified, it is assumed to be int .

What is parameter declaration?

A formal parameter declaration specifies the name and data type of the parameter, and (optionally) its mode and default value. A formal parameter declaration can appear in the following: "Function Declaration and Definition" "Procedure Declaration and Definition" "CREATE FUNCTION Statement"

Can you declare a variable in a parameter?

Parameter, local, and instance variablesParameters are declared in between the parentheses in the header of a method. Local variables are declared between the curly-braces of a method, in a statement (which needs to end with a semicolon).

Is it possible to have a function that has no parameters?

The lesson brief states that “Functions can have zero, one or more parameters”.


1 Answers

It means that in the second case, it's the responsibility of the caller to ensure that the arguments provided are of the correct type; no implicit conversion will be provided (other than the default argument promotions). From section 6.5.2.2:

If the expression that denotes the called function has a type that does not include a prototype, the integer promotions are performed on each argument.

...

If the expression that denotes the called function has a type that does include a prototype, the arguments are implicitly converted, as if by assignment, to the types of the corresponding parameters.

So calling code like this will be ok:

char   x = 3;
char   y = 7;
max(x, y);  // Equivalent to max((int)x, (int)y)

because x and y are promoted to int before being placed on the stack.

However, code like this will not be ok:

double x = 3.0;
long   y = 7;
max(x, y);  // Uh-oh

x and y will be placed on the stack as double and long, but max() will attempt to read two ints, which will result in undefined behaviour (in practice, the raw bits will be reinterpreted).

This is one reason not to use the second form; the only reason it's in the standard is to provide backward compatibility with (extremely) legacy code. If you're using GCC, you can enforce this by using the -Wold-style-definition flag; I would hope that other compilers would offer something equivalent.

like image 187
Oliver Charlesworth Avatar answered Sep 19 '22 07:09

Oliver Charlesworth