Function prototype - disable argument checking

From a K & R book in C, I realized that if a function prototype declaration omits arguments (as in int foo(); ), type checking and argument checking are disabled, and nothing is supposed about arguments compatible with older versions from C and therefore it doesn't violates outdated code.

But the following code generates a compilation error that is incompatible with prototypes:

 #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 explanation?

+6
source share
5 answers

When a function is declared more than once, all declarations must be of a compatible type (C11 6.2.7 / 2). In your code, f declared twice - the definition is also considered a declaration.

The definition of "compatible function type" is given in C11 6.7.6.3/15:

For two types of functions that must be compatible, both must indicate compatible return types. Moreover, lists of parameter types, if they are both present, must agree on the number of parameters and use a terminator with an ellipsis; corresponding parameters must have compatible types. If one type has a list of parameter types, and the other type is specified by the function declarator, which is not part of the function definition and contains an empty list of identifiers, the parameter list should not have an ellipsis terminator, and each parameter type must be compatible with the type that arises due to default promotions. If one type has a list of parameter types, and another type is determined by the definition of a function that contains a (possibly empty) list of identifiers, both are consistent in the number of parameters, and the type of each prototype parameter must be compatible with the type that arises from the application of the promo default arguments to the type of the corresponding identifier. (When determining type and composite type compatibility, each parameter declared using a function or array type is accepted as having an adjusted type, and each parameter declared using a qualified type is accepted as having an unqualified version of its declared type.)

Therefore, void test() and void test(float) are incompatible. In other words, after viewing void test(); Any prototype should use only those types that do not change by default. float changes to double under these promotions.

I believe this has always been the case with the first standard C.

+5
source

Define a function with a parameter of type double .

 void test(double a) { //... } 

The problem is this call.

 test(34.5f); 

the default argument argument is used, which converts the argument to a double type.

+1
source

According to the error message, the type of the argument, for which the tooltip is used by default, corresponds to the declaration of the list of empty parameters . Therefore, the problem is that the float will advance to int , which will then lead to a mismatch with the definition parameter of the float function.

Declaration:

 void test(); 

It tells the compiler that there is a test function that has no parameters and does not return a value.

Definition:

 void test(float a) 

It tells the compiler that there really is test() , and also provides a declaration.

+1
source

So, finally, from all the answers given here and from a small number of readings, here is what I found out (I sent it as an answer so that it would be useful to anyone who might encounter this question in the future):

  • When I called test(23.4f) , the parameter is automatically "forced" in double and will be called as test(double) , since the prototype is not specified (for arguments, at least)
  • Since any call that I make using any arguments will be converted to a "default promotion", I cannot have functions declared as test(float) , since it will never be used / called. So test(double) works, but test(float) does not work.

Correct me if I am wrong and I will edit my answer.

0
source

You told gcc compile c11 code, not like K & R.

I looked at the -std= options, but none of them stand out as useful. Perhaps abandoning the standard language setting will help. Or specify it as c89 .

C11 always requires full-size prototypes. Therefore, the first use gives the function as a parameter = (void) . In pre-C ++, this would really mean "there may or may not be passed parameters."
-one
source

Source: https://habr.com/ru/post/1014691/


All Articles