Home > Back-end >  Why do these two methods work to solve the "implicit declaration of function"?
Why do these two methods work to solve the "implicit declaration of function"?

Time:12-16

I am new to C, and I encounter a very confusing phenomenon. Here is the code snippet:

// hello.c
#include <stdio.h>

int main(int argc, char **argv) {
    printf("Hello, %s!\n", getlogin());
}

When I use cc hello.c to compile it, I'll get a warning message and the run ./a.out will cause a segment fault.

Just like this:

client@ubuntu:01$ cc hello.c 
hello.c: In function ‘main’:
hello.c:5:26: warning: implicit declaration of function ‘getlogin’ [-Wimplicit-function-declaration]
    5 |  printf("Hello,  %s!\n", getlogin());
      |                          ^~~~~~~~
hello.c:5:19: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat=]
    5 |  printf("Hello,  %s!\n", getlogin());
      |                  ~^      ~~~~~~~~~~
      |                   |      |
      |                   char * int
      |                  %d
client@ubuntu:01$ ./a.out 
Segmentation fault (core dumped)

But these two methods will work to solve this problem: Here is the first method

#include <stdio.h>
#include <unistd.h>

int main(int argc, char **argv) {
    printf("Hello, %s!\n", getlogin());
}

And here is the second method:

#include <stdio.h>

char * getlogin();

int main(int argc, char **argv) {
    printf("Hello, %s!\n", getlogin());
}

I can understand the first solution, but why does the second solution can work? Thank you, my friend.

CodePudding user response:

With the second solution, the object file will compile, because the declaration of the function was provided, and the call to that function is compatible with that declaration.

Most compilers by default will link programs against the standard C library on that platform. The linker will find the getlogin symbol in that library and use that. Therefore the linker is also satisfied.

The following program works (and does nothing):

char *getlogin(void);

int main(void)
{
    (void) getlogin();
}

Now when you compile it with normal parameters, it will most likely just work.

However, if you pass -nostdlib or use whatever method your compiler might use to avoid linking to the standard library, it does not work, and the linker should complain. For example:

undefined reference to `getlogin'

CodePudding user response:

C is now a rather old language: it was created in the 70' as a tool to build Unix kernels. Even though it has evolved a lot, it still has at some place the good old you are the boss, and I shall obey rule. Function declaration is one of this places:

  • external functions (which will be resolved at link time) have to be declared in the compilation unit, and have to be provided to the linker. Both operations are completely independent (which often leads to crashes if the linked function and the declared one are not the same...)
  • if a function is used without being declared, it is just supposed to return an int value and give no indication on the expected parameter (here the missing declaration is taken as int getlogin()).

The underlying rationale, is that it allows lazy programmers to skip function declarations if they are sure to always pass the correct parameters.

That was for the context, next here is the answer to your question: include files of the standard library are nothing more than a collection of declarations. And as the #include directive only includes the text of the external file, including a header in a compilation unit, or manually typing the declaration are strictly equivalent on a compiler point of view.


It does not mean that you can do either way. Including header files is a guarantee that you will consistently use the correct declaration, while manually adding the declaration in all the compilation unit adds a great risk for typos, and will make maintenance harder because the declaration are scattered among plenty of files instead of being cleanly and nicely in one single place.

CodePudding user response:

Declaration is giving information about variable type or function to the compiler,In your case giving information about function return type and its arguments to the compiler

Before using any standard functions we must have to check with their declarations(must be same as declared in header files) to avoid such warnings, else we are required to include header files which contains those declarations.

And getlogin() is not recommended to use getlogin() c function returns NULL and error "No such file or directory"

  •  Tags:  
  • c
  • Related