0

I have a simple C program that makes a call to the wait() function. However, my program doesn't include sys/wait.h. It still compiles and works fine. It's job is essentially to rewrite the process image with the command line arguments.

During compilation, I get this warning:

my_program.c: in function 'main' warning: implicit declaration of function 'wait', did you mean 'main'?

My program looks like this... It does exactly what I want it to do. I just don't know why wait() is still being defined when I don't include it.

#include <stdlib.h>
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
int main(int argc, char **argv)
    {
    pid_t my_pid;
    my_pid = fork();
    if (my_pid < 0)
        {
        printf("The fork didn't work! Terminate\n");
        exit(0);
        }
    if (my_pid != 0)
        {
        // Parent block
        printf("The parent will now wait\n");
        wait(NULL);
        printf("Done!\n");
        }
    else
        {
        // Child block
        int resp;
        resp = execvp(*(argv+1), argv+1);
        printf("There was an error. Response code: %d\n Errno: %s\n", resp, stderror(errno));
        }
    }

Yet when I add #include <sys/wait.h>, the program compiles without a warning. Why is it able to compile in the first place, without sys/wait.h imported?

cigien
  • 57,834
  • 11
  • 73
  • 112
Daniel C
  • 31
  • 6
  • What command do you run to compile the program? Most likely the definition of `wait()` function is compiled in another translation unit (i.e. `sys/wait.c` is compiled separately). The compiler only warns you because you didn't explicitly mention in the `main` program that you want to use this function. – mercury0114 Oct 13 '20 at 18:54
  • "*It still compiles and works fine*" -- no, it emits a warning during compilation. Under some circumstances that may be *acceptable*, but it is a clear indication that things are not "fine". – John Bollinger Oct 13 '20 at 18:55
  • @mercury0114 I'm compiling it with "gcc my_program.c", with no other arguments that should impact the actual compilation. – Daniel C Oct 13 '20 at 18:55
  • @JohnBollinger By "Compiles and works fine" I mean there is no noticeable difference during execution with and without the including of sys/wait.h – Daniel C Oct 13 '20 at 18:56
  • I don't doubt that the program works either way, but the compiler has specifically told you that there is a problem with your code when the header is not included. I'm sure I sound nitpicky, but it's hard to understate the importance of paying attention to compiler warnings. In this case, it happens to work because your compiler provides an extension to support legacy code, and the `wait()` function happens to have a signature that can take advantage of that. You will not always be so lucky. – John Bollinger Oct 13 '20 at 19:00
  • @JohnBollinger I don't think you sound nitpicky, this exactly answered my question. Thank you for the help. – Daniel C Oct 13 '20 at 19:11
  • @JohnBollinger Because wait() is defined as an extern function in sys/wait.h (https://code.woboq.org/gcc/include/sys/wait.h.html), is that why my program is able to access it even though the header wasn't included? – Daniel C Oct 13 '20 at 19:21
  • Not particularly, @DanielC. That's more or less why you are able to use `wait()` *at all*, header or no. The key attributes of `wait()` that make it usable according to the (removed) C90 rules for implicit function declarations are (1) it returns `int`; (2) it is non-variadic, and (3) the type of its argument is not subject to the default argument promotions. But the thing you should actually be taking away is that it is poor form and unwise to take advantage of such legacy features when writing new code. Make sure all the functions you call have in-scope declarations. – John Bollinger Oct 13 '20 at 19:46

1 Answers1

0

This is a "C" program, not a "C++" program. There is no linkage for different calling sequences. C originally did not require that called functions be pre-defined. So your compiler just assumes that there must be a function it can call called wait and that it returns an integer value. You provide an argument NULL which is pushed on the stack.

However, not telling the compiler what you are calling is really bad programming practice, so you should include sys/wait.h

vy32
  • 28,461
  • 37
  • 122
  • 246
  • How does gcc connect the wait() function that hasn't been declared, to the wait() function in the library that hasn't been included? – Daniel C Oct 13 '20 at 19:27
  • gcc doesn't connect it. The linker connects it. That's a program called `ld`. gcc creates an object file and the linker links and produces an executable. – vy32 Oct 13 '20 at 23:17