2

If there is no function prototype, a function is implicitly declared by its first appearance in an expression.

In C, if a function return anything else than int it is a good habit to declare the function inside the caller function like 1st example of code.

But you are always constrained by the compiler to write the prototype, the reason is that he does not know who the function is because it is declared underneath the main() function.

The question is: These two are equivalent? Will either writing the prototype or declaring explicitly the function inside the main() return the wanted result? How can it return a bad value if you are constrained always to use one of this two ways?

  1. if the function is declared in the same script as the caller function is (here main())
    • prototype
    • declare explicitly function in main().
  2. if the function is declared in another file
    • prototype
    • declare explicitly function in main()

E.g:

int main()
{
    double doSomething(int a);
    printf("%d", doSomething(2) );
}
double doSomething(int a)
{
     return a * 2.0;
}

vs

double doSomething(int a);

int main()
{
    printf("%d", doSomething(2) );
}
double doSomething(int a)
{
     return a * 2.0;
}

This thread is almost what i needed but it did not answer all my questions. C language - calling functions without function prototype

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
Cătălina Sîrbu
  • 1,253
  • 9
  • 30

2 Answers2

4

These two declarations are equivalent until in the first case the function doSomething will be required in some other function except main.

In this code snippet

int main()
{
    double doSomething(int a);
    //..

there is a function prototype of the function doSomething.

From the C Standard

A function prototype is a declaration of a function that declares the types of its parameters

That is before the function definition that is also its declaration the name of the function will be visible only in the block scope of main.

Consider the following program

#include <stdio.h>

void g( void )
{
    f( 20 );
}

int main(void) 
{
    void f( int );

    f( 10 );

    return 0;
}

void f( int x )
{
    printf( "x = %d\n", x );
}

The compiler will issue an error for this statement

    f( 20 );

because the name f is not yet declared.

But this statement

    f( 10 );

is correct because the name inside the block scope of main is already declared.

To make it more clear take into account that functions always has a linkage opposite to variables declared in a block scope without a storage class specifier.

So this declaration in main

    double doSomething(int a);

is equivalent to the declaration

    extern double doSomething(int a);

And the linker will find the function definition even if the function initially is declared in a block scope.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • So a prototype can be written even inside the main function? Is not mandatory to be outside? – Cătălina Sîrbu Nov 02 '19 at 11:26
  • Does this mean that the `doSomething` prototype is only visible (known) in `main` and any use of it (outside `main`) before its definition (i.e. the function implementation) will cause an error? – Paul Ogilvie Nov 02 '19 at 11:27
  • @CătălinaSîrbu As I wrote if a function is not required outside the function main when its prototype can be placed in the scope of main. – Vlad from Moscow Nov 02 '19 at 11:27
  • And how can u get an unwanted `return` type ? I mean if the function's return type is `double` can you give me an example how can it be converted to `int`( the default ) due to lack of declarations ? It is supposed that the program should not give any errors – Cătălina Sîrbu Nov 02 '19 at 11:29
  • @PaulOgilvie Yes the name will not be declared in other scopes before the function definition. – Vlad from Moscow Nov 02 '19 at 11:30
  • So an easy way to overcome this problem would be to declare the function before `main()` and in this way i would get rid of all prototypes declarations ? – Cătălina Sîrbu Nov 02 '19 at 11:32
  • @CătălinaSîrbu A declaration of a function with declaration of its parameters is already a prototype. The scope of an identifier starts from the placement of the identifier. So if for example you want that your function would be called from other function that place the function declaration before the definition of other function or inside the definition of other function. In any case you have to make the name visible. – Vlad from Moscow Nov 02 '19 at 11:36
  • @PaulOgilvie, are you sure that what you see is not the effect of implicit declarations? – AProgrammer Nov 02 '19 at 11:39
  • @PaulOgilvie The Microsoft compiler does not support C99. – Vlad from Moscow Nov 02 '19 at 11:46
  • @VladfromMoscow could you please provide an example when a `double` function could `return` an `int` value due to an implicit conversion caused by not properly declaring the function as it should? – Cătălina Sîrbu Nov 02 '19 at 11:55
  • @CătălinaSîrbu Just return an integer in a return statement. – Vlad from Moscow Nov 02 '19 at 12:04
  • @VladfromMoscow should't that be automatically converted to `double` as the type-return modifier of the function is `double`? – Cătălina Sîrbu Nov 02 '19 at 12:08
  • @CătălinaSîrbu Yes there will e used the usual arithmetic conversions. – Vlad from Moscow Nov 02 '19 at 12:10
1

In modern C, you should always declare a function before using it. (That includes defining a function before using it, because a definition is a declaration.) Implicit declaration of functions to return int is a behavior of very old verions of C. It should not be used, compilers should at least warn about it, and you should set your compiler to make it an error, not a warning.

Functions are usually declared outside of other functions. There is nothing explicitly wrong about declaring a function inside another function, but we rarely do it because we generally want functions to be visible throughout a translation unit, not just in one specific place. (A translation unit is one source file together with all the files it includes via #include directives.) The names of functions obey the same scope rules as object names: If it appears outside of any function, it has file scope. If it appears inside a block (a list of statements inside braces, { … }, which includes function bodies), it has block scope and is only visible in that block.

Whether a function is declared at file scope or block scope will not affect how it behaves.

main is not special in this regard. You are likely asking about main because you are early in your programming education, and you mostly call functions just from main. However, functions may be called from other functions, and the rules about scope and name visibility are not particular to main. If a function is declared at file scope, its name is visible throughout the rest of the translation unit. If a function is declared at block scope, whether inside main or another function, its name is visible throughout the rest of that block.

If a function is defined to return double but you use it without declaring it, and your compiler allows that, then you can expect your program to work incorrectly. The compiler will not automatically convert double to int. The function type is important to tell the compiler what the function returns because the compiler expects certain bits to be in certain places when the function returns, and it writes instructions relying on that.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • I don't think you can declare a function inside another one. That is forbidden by C (in your _There is nothing explicitly wrong about declaring a function inside another function_) – Cătălina Sîrbu Nov 02 '19 at 11:59
  • 1
    @CătălinaSîrbu: Of course you can **declare** a function inside another function. `int main(void) { int square(int); }` is strictly conforming C. You cannot **define** a function inside another function in strictly conforming C, although it is not forbidden in conforming C; C implementations may permit it. – Eric Postpischil Nov 02 '19 at 12:03
  • Oh! i confused the terms – Cătălina Sîrbu Nov 02 '19 at 12:06