53

What is meant by the term "implicit declaration of a function"? A call to a standard library function without including the appropriate header file produces a warning as in the case of:

int main(){
  printf("How is this not an error?");
  return 0;
}

Shouldn't using a function without declaring it be an error? Please explain in detail. I searched this site and found similar questions, but could not find a definitive answer. Most answers said something about including the header file to get rid of the warning, but I want to know how this is not an error.

S.S. Anne
  • 15,171
  • 8
  • 38
  • 76
Bazooka
  • 1,428
  • 4
  • 15
  • 24
  • 4
    The standard C library is by default linked into builds; e.g., with gcc you have to explicitly pass -nostdlib as an argument to the compilation to force it to not link with libc. – tbert Feb 07 '12 at 19:50
  • 2
    @tbert That's why the linker doesn't complain, but the linker has precious little effect on what the compiler does with C code. –  Feb 07 '12 at 19:51
  • See also http://stackoverflow.com/questions/22500/what-are-the-major-differences-between-ansi-c-and-kr-c – Zan Lynx Feb 07 '12 at 19:51
  • 2
    i looked up K&R and it says that if no prior declaration of the function is visible in the scope then the first instance of functions use is assumed to be a declaration with return type int and nothing is assumed about the parameters. Thanks for your input everybody. – Bazooka Feb 07 '12 at 20:19
  • possible duplicate of [Are prototypes required for all functions in C89, C90 or C99?](http://stackoverflow.com/questions/434763/are-prototypes-required-for-all-functions-in-c89-c90-or-c99) – Ciro Santilli OurBigBook.com May 13 '15 at 07:26
  • Repost link above because HTTP links are not indexed https://stackoverflow.com/questions/434763/are-prototypes-required-for-all-functions-in-c89-c90-or-c99 – user202729 Feb 24 '21 at 07:31

7 Answers7

89

It should be considered an error. But C is an ancient language, so it's only a warning.
Compiling with -Werror (GCC) fixes this problem.

When C doesn't find a declaration, it assumes this implicit declaration: int f();, which means the function can receive whatever you give it, and returns an integer. If this happens to be close enough (and in case of printf, it is), then things can work. In some cases (e.g., the function actually returns a pointer, and pointers are larger than ints), it may cause real trouble.

Note that this was fixed in newer C standards (C99 and C11). In these standards, this is an error. However, GCC doesn't implement these standards by default, so you still get the warning.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
ugoren
  • 16,023
  • 3
  • 35
  • 65
  • 4
    Your answer is right on spot and says exactly what K&R says. Thanks for the concise explanation. – Bazooka Feb 07 '12 at 20:22
  • 2
    Note that even in the days when implicit declarations were allowed, they still resulted in UB for variadic functions like `printf`. – R.. GitHub STOP HELPING ICE Feb 07 '12 at 23:42
  • 2
    @R.., In principle you're right. In practice, most implementations handle a variadic function with was given n parameters just like a normal function which got n parameters, so things work. – ugoren Feb 08 '12 at 05:35
  • 2
    This answer was right 24 years ago. It is wrong today. The current C standard (C11) and the widely-implemented previous one (C99) both explicitly forbid calling undeclared functions. –  Dec 01 '13 at 00:11
  • @H2CO3, I think it's true today, because compilers don't use newer standards by default. Anyway, I added this information. – ugoren Dec 01 '13 at 08:24
  • 1
    @ugoren One overly popular compiler, `clang` defaults to C99, yet another very significant one, `gcc`, supports it. The only widely used compiler on the market, Microsoft's MSVC, is the only one that doesn't have C89 support. So, "compilers don't use newer standards" is not true. –  Dec 01 '13 at 08:36
  • @H2CO3, IMHO, only the default matters (almost). Thus, `clang` uses c99, `gcc` and `msvc` don't. – ugoren Dec 01 '13 at 08:45
  • @ugoren Why would the default matter only? If I want C99 support, I tell my compiler to treat my code as C99, every decent programmer knows that. The only people who don't know about compiler flags are the very beginners, whom I consider an entirely insignificant factor in this issue. –  Dec 01 '13 at 08:50
  • @ugoren: in which case the function returns a pointer? and what about environments where int & pointers are of same size. (4 bytes) ? – Destructor Oct 19 '15 at 13:31
  • 1
    @PravasiMeet, If `int` and pointer are the same size, some trouble is saved (but not all). Code that returns a pointer may work without a declaration in 32bit systems, and fail in 64bit systems, so it's not portable. That's a reason why you should always use a declaration, even if it works without it. – ugoren Oct 19 '15 at 14:48
  • GCC defaults to `gnuc11`. The standard doesn't say that a conforming implementation must **reject** implicit declarations. – Antti Haapala -- Слава Україні Mar 02 '17 at 11:54
  • 2
    And same size is not enough - floats and ints are of same size in majority of platforms but would be returned in differently – Antti Haapala -- Слава Україні Mar 02 '17 at 11:56
  • So bad solution, I try with fprintf, and I get the same error, I think not is correct your bad solution. –  Apr 30 '17 at 15:59
  • Newer standards explicitly allow the compiler to continue using implicit `int`; they just need to print a warning. Is that the case for implicit function declarations also? – Daniel H Sep 29 '17 at 18:41
  • 1
    @DanielH yes, the standard explicitly says that a conforming compiler is allowed to compile an invalid program, provided that it issues required diagnostics. – Antti Haapala -- Слава Україні Oct 26 '18 at 10:32
  • @DanielH: In cases where the authors of the C Standard couldn't agree whether a construct should be allowed, the Standard generally specifies that it's not allowed within *strictly conforming C programs*, but waives jurisdiction over whether implementations might usefully process programs containing the construct anyhow. Some such constructs have been effectively deprecated in favor of better ways of doing things (e.g. declaring functions before use), but for some others no better alternatives have ever existed, and so the right way of handling things would be for compilers to... – supercat Mar 13 '23 at 21:25
  • ...issue the mandated useless diagnostic, which the programmer would then ignore, and then have the compiler process the program as though the unfortunate requirement didn't exist. – supercat Mar 13 '23 at 21:25
21

Implicit declarations are not valid in C.

C99 removed this feature (present in C89).

GCC chooses to only issue a warning by default with -std=c99, but a compiler has the right to refuse to translate such a program.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
ouah
  • 142,963
  • 15
  • 272
  • 331
  • 2
    On a related note, `-pedantic-errors` will make GCC (or CLang, for that matter) behave as per standard here, and refuse to compile (read: emit an error and abort). – Tim Čas Feb 10 '15 at 20:12
9

To complete the picture, since -Werror might considered too "invasive",
for GCC (and LLVM), a more precise solution is to transform just this warning in an error, using the option:

-Werror=implicit-function-declaration

See How can I make this GCC warning an error?.

Regarding general use of -Werror: Of course, having warningless code is recommendable, but in some stage of development it might slow down the prototyping.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Antonio
  • 19,451
  • 13
  • 99
  • 197
4

Because of historical reasons going back to the very first version of C, it passes whatever type the argument is. So it could be an int or a double or a char*. Without a prototype, the compiler will pass whatever size the argument is and the function being called had better use the correct argument type to receive it.

For more details, look up K&R C.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Zan Lynx
  • 53,022
  • 10
  • 79
  • 131
3

C is a very low-level language, so it permits you to create almost any legal object (.o) file that you can conceive of. You should think of C as basically dressed-up assembly language.

In particular, C does not require functions to be declared before they are used. If you call a function without declaring it, the use of the function becomes its (implicit) declaration. In a simple test I just ran, this is only a warning in the case of built-in library functions like printf (at least in GCC), but for random functions, it will compile just fine.

Of course, when you try to link, and it can't find foo, then you will get an error.

In the case of library functions like printf, some compilers contain built-in declarations for them so they can do some basic type checking, so when the implicit declaration (from the use) doesn't match the built-in declaration, you'll get a warning.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Greg Humphreys
  • 968
  • 1
  • 7
  • 11
  • Any idea why does gcc do so for "build in functions" like printf ?? I seems to work well with the user defined functions. – Bazooka Feb 07 '12 at 20:34
  • 4
    "In particular, C does not require functions to be declared before they are used." - it does. C89 (which allowed this) is not the current standard. C11 is, and neither C11 nor its overly popular predecessor, C99, allow calling implicitly declared functions. –  Dec 01 '13 at 00:13
3

An implicitly declared function is one that has neither a prototype nor a definition, but is called somewhere in the code. Because of that, the compiler cannot verify that this is the intended usage of the function (whether the count and the type of the arguments match). Resolving the references to it is done after compilation, at link-time (as with all other global symbols), so technically it is not a problem to skip the prototype.

It is assumed that the programmer knows what he is doing and this is the premise under which the formal contract of providing a prototype is omitted.

Nasty bugs can happen if calling the function with arguments of a wrong type or count. The most likely manifestation of this is a corruption of the stack.

Nowadays this feature might seem as an obscure oddity, but in the old days it was a way to reduce the number of header files included, hence faster compilation.

Blagovest Buyukliev
  • 42,498
  • 14
  • 94
  • 130
  • 4
    Citation needed. I don't implicit declarations were included as a feature to improve compile time. As far as I can tell, the early evolution of C (from B) started with no types but `int`, and thus knowing type information about a function was not so important... – R.. GitHub STOP HELPING ICE Feb 07 '12 at 23:44
  • 1
    where you say "prototype" you mean "declaration". Some declarations are not prototypes. – M.M Jan 31 '17 at 01:52
0

First you declare then you type the main() function:

void oi(){printf("oi");};
int main(){oi();return 0;};
CreepyRaccoon
  • 826
  • 1
  • 9
  • 19