Bala Kumar
Bala Kumar

Reputation: 355

Function Prototype - Turning off argument checking

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

Answers (5)

msc
msc

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

Bala Kumar
Bala Kumar

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) :

  • When I called 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)
  • Since any call i make using any arguments will be converted to 'a default promotion', i can't have functions declared as 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

Vlad from Moscow
Vlad from Moscow

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

M.M
M.M

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

wallyk
wallyk

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

Related Questions