Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does a function prototype with an empty argument list conflicts with one that has a char argument?

With the code below, both clang and gcc called with -std=c11 complain about conflicting types for foo.

int foo();

int main(void) {
  return foo(0);
}

int foo(char a) {
   return a;
}

According to the answer in https://stackoverflow.com/a/13950800/1078224, in (older?) C standards the type int has been assumed when no variable type was given. However, the C11 standard draft (http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf), section 6.7.6.3, $14 says that

The empty list in a function declarator that is not part of a definition of that function specifies that no information about the number or types of the parameters is supplied.

From this I conclude that the code above should be actually valid. Or am I missing some other relevant section of the standard?

like image 781
Inkane Avatar asked Feb 18 '14 15:02

Inkane


People also ask

What are function prototypes and what is its purpose?

A function prototype is a definition that is used to perform type checking on function calls when the EGL system code does not have access to the function itself. A function prototype begins with the keyword function, then lists the function name, its parameters (if any), and return value (if any).

What happen if there is no function prototype?

In C language, when we don't provide a prototype of a function, the compiler assumes that function returns an integer.

What is not included in function prototype?

In computer programming, a function prototype or function interface is a declaration of a function that specifies the function's name and type signature (arity, data types of parameters, and return type), but omits the function body.

What is the difference between function header function prototype and arguments?

The only difference between the function prototype and the function header is a semicolon (see diagram below). The function definition is placed AFTER the end of the int main(void) function. The function definition consists of the function header and its body.


1 Answers

C 2011 (N1570) 6.7.6.3 15:

For two function types to be compatible, both shall specify compatible return types. Moreover, the parameter type lists, if both are present, shall agree in the number of parameters and in use of the ellipsis terminator; corresponding parameters shall have compatible types. If one type has a parameter type list and the other type is specified by a function declarator that is not part of a function definition and that contains an empty identifier list, the parameter list shall not have an ellipsis terminator and the type of each parameter shall be compatible with the type that results from the application of the default argument promotions.… [Emphasis added.]

char is promoted to int, so char a is not compatible with an empty list. int a would be; int foo(); int foo(int a); is allowed.

Essentially, the reason for this is that, if you declare a function int foo() and then call it, say with int foo(3), the compiler has to know what to pass it. The rules, derived from history, are to perform the default argument promotions. So int foo(3) gets called as if it were int foo(int).

Then, if you later define the function with int foo(char), the definition will not match the call. In many C implementations a char and an int may be put in the same place for calling a function, but a C implementation could do something different. A float and a double would be a greater conflict.

like image 129
Eric Postpischil Avatar answered Oct 18 '22 19:10

Eric Postpischil