Home > Software engineering >  Should a function declaration without the type of its parameters compile in ANSI C?
Should a function declaration without the type of its parameters compile in ANSI C?

Time:10-15

I'm investigating ANSI C. Should this compile? Could this code comply with a newer standard? (It tried but always got the error)

#include <stdio.h>
#include <stdlib.h>


float declaration();
float prototype(float);


int main(void)
{
    printf("declaration: %f\n", declaration(10));
    printf("prototype: %f\n", prototype(10));

    return 0;
}


float declaration(float x)
{
    return x;
}

float prototype(float x)

{
    return x;
}

I get a conflicting type errors with -ansi -pedantic-errors -pedantic :

gcc.exe -Wall -g -pedantic-errors -pedantic -ansi -save-temps  -c main.c -o main.o
gcc.exe  -o out.exe main.o   
main.c:18:7: error: conflicting types for 'declaration'
   18 | float declaration(float x)
      |       ^~~~~~~~~~~
main.c:19:1: note: an argument type that has a default promotion cannot match an empty parameter name list declaration
   19 | {
      | ^
main.c:5:7: note: previous declaration of 'declaration' was here
    5 | float declaration();
      |       ^~~~~~~~~~~

What is confusing me is that the standard says:

6.2.1 Scopes of identifiers... A function prototype is a declaration of a function that declares the types of its parameters.

Which may mean that you can declare a function without them...

Thanks!

CodePudding user response:

This should not compile because if you have an old-style function declaration and a prototype in the same scope, all the parameter types must be compatible with themselves after default argument promotion. float is not such a type because it promotes to double.

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 (link).

So:

float declaration();
float declaration(float x) { return x; } // fail

float declaration2();
float declaration2(double x) { return x; } // ok

If you jam a call

 declaration2(10);

between the declaration and the definition of declaration2, this is undefined behaviour but not a diagnosable error. For the call to be valid, you either need to see a prototype at the call site, or actual argument types should be compatible (after default argument promotions) with parameter types. This is not the case for int and double.

  • Related