Why don't we get a compile-time error even if we do not include stdio.h in a C program?

How does the compiler know the prototype of the sleep function or even the printf function when I didn't include the header file at all?

Also, if I specify sleep(1,1,"xyz") or any arbitrary number of arguments, the compiler still compiles it. But it’s strange that gcc can find the definition of this function at the time of reference, I don’t understand how this is possible, because the actual sleep() function takes only one argument, but our program mentioned three arguments.

 /********************************/ int main() { short int i; for(i = 0; i<5; i++) { printf("%d",i);`print("code sample");` sleep(1); } return 0; } 
+6
c compiler-construction
source share
7 answers

Without a more specific prototype, the compiler will assume that the function returns int and accepts any number of arguments that you provide.

Depending on the CPU architecture, the arguments can be passed to registers (for example, from a0 to a3 on MIPS) or by pushing them onto the stack, as in the original x86 calling convention. In any case, passing additional arguments is harmless. The called function will not use the passed registers or refer to additional arguments on the stack, but nothing bad happens.

Skipping fewer arguments is more problematic. The function called will use any garbage located in the appropriate register or stack location, and hijinks may appear.

+10
source share

In classic C, you don't need a prototype to call a function. The compiler will output that the function returns int and accepts an unknown number of parameters. This may work on some architectures, but it will fail if the function returns something other than int, like a structure, or if there are any parameter conversions.

In your example, the dream is being watched, and the compiler assumes a prototype, for example

 int sleep(); 

Note that the argument list is empty. In C, this is NOT the same as void. It actually means "unknown." If you are writing K & RC code, you may have unknown parameters using code like

 int sleep(t) int t; { /* do something with t */ } 

This is all dangerous, especially on some built-in microcircuits, where parameter parameters for the unprotected function are transmitted, differs from the prototype.

Note: prototypes are not needed for binding. Typically, the linker automatically links to the C runtime library, such as glibc on Linux. The connection between your use of sleep and the code that implements it occurs during the connection long after processing the source code.

I would suggest that you use your compiler function to require prototypes to avoid such problems. With GCC, this is the -Wstrict-prototypes command line argument. In CodeWarrior tools, this was the “Require Prototypes” flag in the C / C ++ Compiler Panel.

+5
source share

C will consider int for unknown types. Therefore, he probably believes that sleep has this prototype:

 int sleep(int); 

As for providing a few parameters and binding ... I'm not sure. It surprises me. If this really worked, then what happened at runtime?

+2
source share

This is due to what are called "K and RC" and "ANSI C". In the good old K and RC, if something is not announced, it is assumed that this is int. So any thing that looks like a function call but is not declared as a function will automatically accept the return value of 'int' and the types of arguments depending on the call of the call.

However, later people found out that sometimes it can be very bad. So several compilers added a warning. C ++ made this mistake. I think gcc has flag (-ansic or -pedantic?) That make this condition an error.

So, in short, this is historical baggage.

+2
source share

Other answers cover probable mechanics (all guesses are not specified as a compiler).

The problem you are facing is that your compiler and linker were not configured to include all possible errors and warnings. For any new project, there is (practically) no excuse for this. older projects have more excuses - but strive to maximize their potential

+2
source share

It depends on the compiler, but with gcc (for example, since you mentioned) some of the standard (both C and POSIX) functions have built-in "built-in compilers". This means that the compiler library that comes with your compiler (libgcc in this case) contains an implementation of the function. The compiler will allow the implicit declaration (i.e., using a function without a header), and the linker will find the implementation in the compiler library, because you are probably using the compiler as a linker interface.

Try compiling your objects using the -c flag (only for compilation, without a link), and then directly link them using the linker. You will find that you receive linker errors that you expect.

As an alternative, gcc supports options to disable the use of built-in functions: -fno-builtin or for granular control, -fno-builtin-function . There are other options that may be useful if you are doing something like creating a homegrown kernel or some other metal application.

+1
source share

In an example other than a toy, another file may contain the one you missed. Looking at the output from the preprocessor is a good way to see what you end up compiling.

+1
source share

All Articles