Reputation: 355
From K&R Book on C, I gathered that if the function prototype declaration omits the arguments (as in int foo();
) the type and argument checking is turned off and nothing is assumed about the arguments to be compatible with older versions of C and so it doesn't break legacy code.
But the following code throws a compilation error that the prototypes mismatch:
#include <stdio.h>
void test();
int main(void) {
test(34.5f);
}
void test(float a) {
printf("%f\n", a);
}
Error:
C:\***.c:7:6: error: conflicting types for 'test'
void test(float a) {
^
Any explanations?
Upvotes: 6
Views: 255
Reputation: 34608
According to the error message, an argument type that has a default promotion can’t match an empty parameter name list declaration. So the problem is that float
would be promoted to int
, which would then cause a mismatch with the function definition's float
parameter.
Declaration:
void test();
It's tells the compiler that there exists a function test
which no parameters and not returns a value.
Definition:
void test(float a)
It's tells the compiler what test()
actually is and also provides the declaration as well.
Upvotes: 1
Reputation: 355
So, finally from all the answers given here and from a little bit of reading, here's what i learned (i posted it as an answer so that it would be helpful to anyone who might come across this question in the future) :
test(23.4f)
- The parameter is automatically 'coerced' into double and will be called as test(double)
since no prototype is specified (for the arguments, atleast)test(float)
since it will never be used/called. So, test(double)
works and test(float)
doesn't.Correct me if i'm wrong and i'll edit my answer.
Upvotes: 0
Reputation: 311018
Define the function with the parameter of the type double
.
void test(double a) {
//...
}
The problem is in this call
test(34.5f);
there is used the default argument promotion that converts the argument to the type double.
Upvotes: 1
Reputation: 141618
When a function is declared more than once, all declarations must have compatible type (C11 6.2.7/2). In your code f
is declared twice - the definition also counts as a declaration.
The definition of "compatible function type" is in C11 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. If one type has a parameter type list and the other type is specified by a function definition that contains a (possibly empty) identifier list, both shall agree in the number of parameters, and the type of each prototype parameter shall be compatible with the type that results from the application of the default argument promotions to the type of the corresponding identifier. (In the determination of type compatibility and of a composite type, each parameter declared with function or array type is taken as having the adjusted type and each parameter declared with qualified type is taken as having the unqualified version of its declared type.)
Therefore void test()
and void test(float)
are incompatible. In other words, after seeing void test();
, any prototype must only use types that are unchanged by the default argument promotions. float
changes to double
under those promotions.
I believe this has always been the case since the first C Standard.
Upvotes: 5
Reputation: 57774
You have told gcc
to compile c11
code, not as K&R.
I looked at the -std=
options, but none of them stand out as being useful. Perhaps omitting the language standard parameter altogether would help. Or specify it as c89
.
In c11, full shaped prototypes are always required. So the first use gives the function as having parameter= (void)
. In pre-c++, that indeed would mean "there might or not be parameters passed".
Upvotes: -1