2
votes

According to C How to Program (Deitel):

Standard library functions like printf and scanf are not part of the C programming language. For example, the compiler cannot find a spelling error in printf or scanf. When the compiler compiles a printf statement, it merely provides space in the object program for a “call” to the library function. But the compiler does not know where the library functions are—the linker does. When the linker runs, it locates the library functions and inserts the proper calls to these library functions in the object program. Now the object program is complete and ready to be executed. For this reason, the linked program is called an executable. If the function name is misspelled, it is the linker which will spot the error, because it will not be able to match the name in the C program with the name of any known function in the libraries.

These statements leave me doubtful because of the existence of header file. These files are included during the preprocessing phase, before the compiling one, and, as I read, there are used by the compiler.

So if I write print instead of printf how can't the compiler see that there is no function declared with that name and throw an error?

If it is as the book says, why can I declare function in header files if the compiler doesn't watch them?

2
The compiler can see that there is no function declared with that name and throw an error. It depends on compiler options and version of C used.chux - Reinstate Monica
A modern compiler should at least give a warning during compilation. But some compilers make assumptions about a missing function declaration, and the linker would then find the error. Please enable all compiler warnings, because if the function does exist, but was not declared, those assumptions can be wrong.Weather Vane
Note that some misspellings end up calling a different declared function from the one that was intended. Sometimes the compiler can spot that — if the function parameters in the call don't match the prototype. Sometimes, neither the compiler nor the linker can spot that — if the function parameters in the call match the prototype, but it is just the wrong function.Jonathan Leffler

2 Answers

4
votes

So if I write print instead of printf how can't the compiler see that there is no function declared with that name and throw an error?

You are right. If you made a typo in any function name, any modern compiler should complain about it. For example, gcc complains for the following code:

$ cat test.c 
int main(void)
{
    unknown();
    return 0;
}
$ gcc -c -Wall -Wextra -std=c11 -pedantic-errors test.c
test.c: In function ‘main’:
test.c:3:5: error: implicit declaration of function ‘unknown’ [-Wimplicit-function-declaration]
     unknown();
     ^

However, in pre C99 era of C language, any function whose declaration isn't seen by the compiler, it'll assume the function returns an int. So, if you are compiling in pre-C99 mode then a compiler isn't required to warn about it.

Fortunately, this implicit int rule was removed from the C language since C99 and a compiler is required to issue a diagnostic for it in modern C (>= C99).

But if you provide only a declaration or prototype for the function:

$ cat test.c 
int unknown(void); /* function prototype */

int main(void)
{
    unknown();
    return 0;
}
$ gcc -c -Wall -Wextra -std=c89 -std=c11 test.c
$

(Note: I have used -c flag to just compile without linking; but if you don't use -c then compiling & linking will be done in a single step and the error would still come from the linker).

There's no issue despite the fact, you do not have definition for unknown() anywhere. This is because the compiler assumes unknown() has been defined elsewhere and only when the linker looks to resolve the symbol unknown, it'll complain if it can't find the definition for unknown().

Typically, the header file(s) only provide the necessary declarations or prototypes (I have provided a prototype for unknown directly in the file itself in the above example -- it might as well be done via a header file) and usually not the actual definition. Hence, the author is correct in that sense that the linker is the one that spots the error.

4
votes

So if I write print instead of printf how can't the compiler see that there is no function declared with that name and throw an error?

The compiler can see that there is no declaration in scope for the identifier designating the function. Most will emit a warning under those circumstances, and some will emit an error, or can be configured to do so.

But that's not the same thing as the compiler detecting that the function doesn't exist. It's the compiler detecting that the function name has not been declared. The compiler will exhibit the same behavior if you spell the function name correctly but do not include a prior declaration for it.

Furthermore, C90 and pre-standardization C permitted calls to functions without any prior declaration. Such calls do not conform to C99 or later, but most compilers still do accept them (usually with a warning) for compatibility purposes.

If it is as the book says, why can I declare function in header files if the compiler doesn't watch them?

The compiler does see them, and does use the declarations. Moreover, it relies on the prototype, if the declaration provides one, to perform appropriate argument and return value conversions when you call the function. Moreover, if you use functions whose argument types are altered by the default argument promotions, then your calls to such functions are non-conforming if no prototype is in scope at the point of the call. Undefined behavior results.