ayushi grover
ayushi grover

Reputation: 101

Why can I call a function in C without declaring it but not in C++?

In C++, it is a compiler error to call a function before it is declared. But in C, it may compile.

#include<stdio.h>
int main()
{
   foo(); // foo() is called before its declaration/definition
} 

int foo()
{
   printf("Hello");
   return 0; 
} 

I have tried and know that it is correct but I can't get the reason behind it. Can anyone please explain how the compilation process actually takes place and differs in both the languages.

Upvotes: 8

Views: 9533

Answers (4)

Steve Summit
Steve Summit

Reputation: 47942

Originally, C had no function prototypes, and C++ did not exist.

If you said

extern double atof();

this said that atof was a function returning double. (Nothing was said about its arguments.)

If you then said

double d = atof("1.3");

it would work. If you said

double d2 = atof();    /* whoops, forgot the argument to atof() */

the compiler would not complain, but something weird would happen if you tried to run it.

In those days, if you wanted to catch errors related to calling functions with the wrong number or type of arguments, that was the job of a separate program, lint, not the C compiler.

Also in those days, if you just called a function out of the blue that the compiler had never heard of before, like this:

int i = atoi("42");

the compiler basically pretended that earlier you had said

extern int atoi();

This was what was called an implicit function declaration. Whenever the compiler saw a call to a function whose name it didn't know, the compiler assumed it was a function returning int.

Fast forward a few years. C++ invents the function prototypes that we know today. Among other things, they let you declare the number and types of the arguments expected by a function, not just its return type.

Fast forward a few more years, C adopts function prototypes, optionally. You can use them if you want, but if you don't, the compiler will still do an implicit declaration on any unknown function call it sees.

Fast forward a few more years, to C11. Now implicit int is finally gone. A compiler is required to complain if you call a function without declaring it first.

But even today, you may be using a pre-C11 compiler that's still happy with implicit int. And a C11-complaint compiler may choose to issue a mere warning (not a compilation-killing error) if you forget to declare a function before calling it. And a C11-compliant compiler may offer an option to turn off those warnings, and quietly accept implicit ints. (For example, when I use the very modern clang, I arrange to invoke it with -Wno-implicit-int, meaning that I don't want warnings about implicit int, because I've still got lots of old, working code that I don't feel like rewriting.)

Upvotes: 4

Iharob Al Asimi
Iharob Al Asimi

Reputation: 53006

The fact that the code "compiles" as a program doesn't mean you can do it. The compiler should warn about implicit declaration of the function foo().

In this particular case implicit declaration would declare an identical foo() and nothing bad will happen.

But suppose the following, say this is

main.c

/* Don't include any header, why would you include it if you don't
   need prototypes? */

int main(void)
{
    printf("%d\n", foo()); // Use "%d" because the compiler will
                           // implicitly declare `foo()` as
                           //
                           //              int foo()
                           //
                           // Using the "correct" specifier, would
                           // invoke undefined behavior "too".
    return 0;
}

Now suppose foo() was defined in a different compilation unit1 foo.c as

foo.c

double foo()
{
    return 3.5;
}

does it work as expected?

You could imagine what would happen if you use malloc() without including stdio.h, which is pretty much the same situation I try to explain above.

So doing this will invoke undefined behavior2, thus the term "Works" is not applicable in the understandable sense in this situation.

The reason this could compile is because in the very old days it was allowed by the standard, namely the standard.

The standard has never allowed this so you can't compile a program if you call a function that has no prototype ("declaration") in the code before it's called.

Modern compilers warn about this because of the potential for undefined behavior that can easily occur, and since it's not that hard to forget to add a prototype or to include the appropriate header it's better for the programmer if the compiler can warn about this instead of suddenly having a very unexplicable bug.


1It can't be compiled in the same file because it would be defined with a different return type, since it was already implicitly declared

2Starting with the fact that double and int are different types, there will be undefined behavior because of this.

Upvotes: 16

H. Guijt
H. Guijt

Reputation: 3365

When C was developed, the function name was all you needed to be able to call it. Matching arguments to function parameters was strictly the business of the programmer; the compiler didn't care if you passed three floats to something that needed just an integer.

However, that turned out to be rather error prone, so later iterations of the C language added function prototypes as a (still optional) additional restriction. In C++ these restrictions have been tightened further: now a function prototype is always mandatory.

We can speculate on why, but in part this is because in C++ it is no longer enough to simply know the function name. There can be multiple functions with the same name, but with different arguments, and the compiler must figure out which one to call. It also has to figure out how to call (direct or virtual?), and it may even have to generate code in case of a template function.

In light of all that I think it makes sense to have the language demand that the function prototype be known at the point where the function is called.

Upvotes: 5

abelenky
abelenky

Reputation: 64682

Why can I call a function in C without declaring it?

Because in C, but not in C++, a function without a prototype is assumed to return an int.

This is an implicit declaration of that function. If that assumption turns out to be true (the function is declared later on with return-type of int), then the program compiles just fine.

If that assumption turns out to be false (it was assumed to return an int, but then actually is found to return a double, for example) then you get a compiler error that two functions cannot have the same name. (eg. int foo() and double foo() cannot both exist in the same program)

Note that all of this is C only.
In C++, implicit declarations are not allowed. Even if they were, the error message would be different because C++ has function overloading. The error would say that overloads of a function cannot differ only by return type. (overloading happens in the parameter list, not the return-type)

Upvotes: 1

Related Questions