1

There are a few similar questions asking people to debug their code, where the compiler produces a warning of implicit declaration of functions. I know that this warning is produced because if a function is used without there being a prior declaration, function calls can be treated as implicit declarations.

This code has an intentional bug for educational purposes. There are two implicitly declared functions here: one returns int, the second function returns another data type which is char*.

#include <stdio.h>

int main(void)
{
    function1();
    function2();
}

int function1(void)
{
    printf("function1\n");
    return 2;
}

char* function2(void)
{
    char* word = "function2\n";
    printf(word);
    return word;
}

When I go to compile this code, I get these warnings, and an error:

$ gcc test1.c
test1.c: In function ‘main’:
test1.c:5:5: warning: implicit declaration of function ‘function1’ [-Wimplicit-function-declaration]
     function1();
     ^
test1.c:6:5: warning: implicit declaration of function ‘function2’ [-Wimplicit-function-declaration]
     function2();
     ^
test1.c: At top level:
test1.c:15:7: error: conflicting types for ‘function2’
 char* function2(void)
       ^
test1.c:6:5: note: previous implicit declaration of ‘function2’ was here
     function2();
     ^

First I created the function1 and I was able to compile and run the code without problems. The implicit declaration of int function1() was accepted, even though the compiler produced some warnings.

Then I created the function2 and to my surprise, an error was produced by the compiler and the code rejected. Why was the implicit declaration of char* function2() not accepted? Why didn't the function call as an implicit declaration work?

This is the error:

error: conflicting types for ‘function2’

What is the conflicting type? There is only one type. The function takes no arguments and returns char*.

Why did it work for function1?

Galaxy
  • 2,363
  • 2
  • 25
  • 59
  • 2
    It varies by compiler, but many compilers, when they see an implicit function, simply mark it as 'function returning integer'. So, it defines ```function2``` implicitly as ```int function2()```, but then tries to redefine later on as ```char* function2()```. – Michael Bianconi Jun 04 '19 at 03:02
  • @MichaelBianconi So it does that for function *calls* too? – Galaxy Jun 04 '19 at 03:06
  • `int`eresting stuff – Galaxy Jun 04 '19 at 03:06
  • Seems to be similar to the implicit variables as `int`s rule: https://stackoverflow.com/questions/11064292/declaring-variables-without-any-data-type-in-c – Galaxy Jun 04 '19 at 03:13
  • 1
    In C90, you could implicitly declare functions and be OK as long as the eventual definition agreed with the implicit declaration. Thus, `function1` was (sort of) OK in C90, but `function2` was not because the assumed return type was incorrect In C99 (and later), you are supposed to have a declaration (or definition) of each function in scope before you use the function. Ideally, that should be a prototype declaration so that the function parameter types can be checked. GCC 5.1 and later defaults to C11 mode compilation; earlier versions defaulted to C90 mode. – Jonathan Leffler Jun 04 '19 at 03:39
  • @JonathanLeffler unfortunately even the latest version of gcc still defaults to not issuing an error for calling an undeclared function – M.M Jun 04 '19 at 04:06
  • It gives a warning, though, doesn't it, @M.M? At least for me, my home-built GCC 9.1.0 on macOS 10.14.5 Mojave yields: `x.c:4:12: warning: implicit declaration of function ‘another_func’ [-Wimplicit-function-declaration]` —— `4 | return another_func(x / 2) + 37;`. Since I normally compile with `-Werror`, that becomes an error for me. File `x.c` has 5 lines: `extern int somefunc(int x); int somefunc(int x) { return another_func(x / 2) + 37; }`; each brace is on a line of its own. – Jonathan Leffler Jun 04 '19 at 04:10
  • @JonathanLeffler It gives warning only, but no error. Doesn't stop you from compiling and making the executable. – Galaxy Jun 04 '19 at 04:38
  • @Galaxy — in my book, you should be using `gcc -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes -Werror` as the default compiler flags to GCC. Using `-Werror` converts warnings into errors; it prevents sloppy code from being compiled (including `int main() { … }` — that needs to be `int main(void) { … }`). I seldom run code that doesn't compile cleanly under those options — when I do, it is usually someone else's grubby code that doesn't yet meet my standards, or I'm testing "what happens if …". – Jonathan Leffler Jun 04 '19 at 04:41
  • @JonathanLeffler Testing is fun! – Galaxy Jun 04 '19 at 04:42

0 Answers0