Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The behavior of a C compiler with old-styled functions without prototypes

When my program consists of two files:

main.c

#include <stdio.h>

int main(void) { 
     printf("%lf\n",f());   
     return 0;
 }

func.c

double f(int a) {
 return 1;
}

compiler do not show any errors.

When my program consists of only one file:

main.c

#include <stdio.h>

int main(void) { 
     printf("%lf\n",f());   
     return 0;
 }

double f(int a) {
 return 1;
}

Visual C++ 2008 compiler show the following error:

Error 2 error C2371: 'f' : redefinition; different basic types d:\temp\projects\function1\function1\1.c 8 function1

Can anybody explain this strange behavior?

like image 776
Art Spasky Avatar asked Feb 18 '10 08:02

Art Spasky


People also ask

What happen if there is no function prototype?

In C language, when we don't provide a prototype of a function, the compiler assumes that function returns an integer.

Why function prototype is necessary in C?

The function prototypes are used to tell the compiler about the number of arguments and about the required datatypes of a function parameter, it also tells about the return type of the function. By this information, the compiler cross-checks the function signatures before calling it.

Is it necessary to write function prototype in C?

The function prototype is not needed if the user-defined function is defined before the main() function.

Is a function prototype necessary?

It is not needed, but not using prototypes is bad practice. The compiler can use prototypes to make sure you're calling the function appropriately (using the right number and type of parameters).


2 Answers

C will assume a function has the prototype int func(); unless you have told it otherwise.(Note that in C int func(); and int func(void); are different things)

In your second case, you do a call to f() for which the compiler hasn't seen any prototype, so it assumes it is int f(); . Later on it sees your definition for f() which has a different prototype - and issues an error.

This doesn't happen in the 1. case, as they're in different compilation units.

like image 176
nos Avatar answered Sep 28 '22 15:09

nos


Both the programs are wrong.

Without a prototype in scope, a compiler assumes that a function returns int and takes an unspecified number of parameters.

Let's change your files a bit:

$ cat func.c
double f(int a) {
    return 1.0;
}
$ cat main.c
#include <stdio.h>

int main(void) { 
    double d = f();
    printf("%lf\n", d);
    return 0;
}

When I compile it, gcc warns me (Visual C++ should too, in conformant mode). But let's ignore the warning.

$ gcc -std=c99 -pedantic -W -Wall func.c main.c -o test
func.c:1: warning: unused parameter 'a'
main.c: In function 'main':
main.c:4: warning: implicit declaration of function 'f'
$ ./test
0.000000

It did not print 1, but printed 0. This is because the compiler assumed that f() returned an int, and the assignment d = f(); converted that "int" to a double. The compiler still compiled the code because it couldn't tell that f() wasn't defined the way it was (implicitly) declared. But compiling the above program isn't required by the standard, so the compiler could have rejected it (try with gcc -Werror for example!)

If we have everything in one file:

$ cat func.c >>main.c
$ gcc -std=c99 -pedantic -W -Wall func.c main.c -o test
main.c:4: warning: implicit declaration of function 'f'
main.c: At top level:
main.c:9: error: conflicting types for 'f'
main.c:4: error: previous implicit declaration of 'f' was here
main.c:9: warning: unused parameter 'a'

Now the compiler sees the conflict, and gives you an error message. But, a compiler is not required to reject the above program, it may or may not.

Most compilers don't reject the first program because they don't know if you have a correct definition of the function f() in another translation unit or not. They reject the second program because they know that you don't.

like image 42
Alok Singhal Avatar answered Sep 28 '22 17:09

Alok Singhal