include library in C is required?

Asked

Viewed 524 times

1

I came across the following situation:

Ubuntu 16.01

gcc --version

gcc (GCC) 6.3.0 Copyright (C) 2016 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO Warranty; not Even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

test.c

main() {
    printf("Hello Word.\n");
    printf("pow function : %f \n", pow(10,2));
}

Use this command to compile:

gcc -std=c11  test.c -o test

test.c:3:1: warning: return type defaults to ‘int’ [-Wimplicit-int]
 main() {
 ^~~~
test.c: In function ‘main’:
test.c:4:3: warning: implicit declaration of function ‘printf’ [-Wimplicit-function-declaration]
   printf("Hello Word.\n");
   ^~~~~~
test.c:4:3: warning: incompatible implicit declaration of built-in function ‘printf’
test.c:4:3: note: include ‘<stdio.h>’ or provide a declaration of ‘printf’
test.c:5:35: warning: implicit declaration of function ‘pow’ [-Wimplicit-function-declaration]
   printf("powf function : %d \n", pow(10,2));
                                   ^~~
test.c:5:35: warning: incompatible implicit declaration of built-in function ‘pow’
test.c:5:35: note: include ‘<math.h>’ or provide a declaration of ‘pow’

And ran the generated file:

./test

Hello Word.
pow function : 100.000000

I ask: I am obliged to do the #include <stdio.h> and #include <math.h> ? that goes for all standard library?


Altered file:

#include <stdio.h>
#include <math.h>

int main() {
    printf("Hello Word.\n");
    printf("powf function : %f \n", pow(10,2));
    return 0;
 }

Command to compile (in this case no warnings):

gcc -std=c11  test.c -o test

Exit:

./test

Hello Word.
pow function : 100.000000

In both cases the output is the same.

im1 img2

3 answers

7

If you use something from this library then you have to use yes.

Depending on the compiler and its settings it is possible to find the functions to link.

When it generates Warning means your code is wrong, but it can generate an executable. Whether it will work is a matter of coincidence. May or may not work depending on the operation and the desired result.

Every professional programmer treats warnings as if they were a mistake, because they are errors. Only they do not prevent the compilation.

One thing I always talk about and few hear is that being right and functioning are very different things. What is right is what you want. What works is something circumstantial or coincident. It works, but nothing guarantees that it will continue like this in all situations. One mistake that beginner programmers make, and some are beginners even after decades of doing this, is testing to see that it gave him what he wanted to see and to think that he was right. It is only right that what can be proven happens to the desired in all possible situations, including those that are unlikely to happen.

Of course proving that everything is right all the time is almost unfeasible. That’s why software has bugs. You prove to some extent. The problem is that if you prove only in one situation the chance of the code having a bug may be more than 50%. If you try the easy stuff and leave only the hard stuff without proof, or one or two things you didn’t think of and it’s rare, then the chance of a bug is less than 1%.

Then it is mandatory to put the include, even if it does not prevent compilation in a specific situation.

Note that a compiler ideally configured this would give error nor compile.

If you want to know more about the include already has a question on the subject: How the "#include directive works"?. Also: Using function and header file (header).

4

What’s the point of #include?

The #include is a Preprocessor directive, that is, a transformation of the program text that occurs before the parsing itself. It takes a filename as a parameter and replaces itself with the text of the mentioned file: thus, a line in this way:

#include <stdio.h>

It will be replaced by the contents of the file stdio.h in a specific directory of your machine (in the case of Ubuntu, it is probably /usr/local/include/, but it might be different).

Of course, there are many ways to take advantage of this mechanism, but the standard way to use it is to include so-called header files (in English header files, hence its standard extension .h). These are C language files, but contain only:

  • Preprocessor macro definitions (via #define and other related mechanisms, for example the definition of NULL in stddef.h);

  • Type definitions (for example type FILE * defined in stdio.h or struct tm in time.h);

  • Statements of global variables such as errno in errno.h;

  • Statements of functions, where the file informs the compiler that a function with a given name exists, and what parameters it receives and what type of value it returns;

  • Inclusions of others headers on which headers depend.

And in my particular case?

In your case, you can see that you used two functions: printf() and pow(). The declarations of duties are as follows::

int printf(const char * format, ...);
double pow(double base, double exponent);

When the compiler finds a function invocation that has not previously been declared, it sends a warning complaining and assumes that the function returns int and receives an undetermined number of parameters. In the case of the above two functions, they receive and return primitive types, and therefore the invocation of these function trough works, although the type verification is impaired.

Now, if instead of printf() you tried to use fprintf(), which takes as first parameter a stream guy FILE *, you would need to pass the stream correct (stdout so that the fprintf() reproduces the effects of printf()), which is stated in the header stdio.h. When compiling this code, you would receive an error from undefined symbol 'stdout' and the compilation would stop.

Type system

Another disadvantage of invoking undeclared functions is that this disables type checking for function invocation. You may end up passing a parameter of a wrong type to the function (for example, passing an integer in place of the string formatting for printf()) and the compiler won’t detect the problem.

There at this time you have a program that has compiled, but will have some strange behavior when you perform that function (may generate a protection error or worse: keep running).

TL;DR

If you invoke C standard library functions without loading the corresponding headers, the invocation can function if the function in question does not request as a parameter or returns no value, type or global defined in the header. As programs increase in complexity, the probability of this happening tends to zero.

2

Briefly, the macro #include copies the entire contents of a header file to another header file or source file. Many people confuse the standard C files with the C language itself, and this is a serious mistake. C is only the language itself, the set of syntactic rules and Keywords that make up a program. The C standard library is a work built on the fundamental foundations of language.

Therefore, yes, it is necessary to add #include in all files that make use of functions, macros, variables and data structures of another C file.

Extra: Some compilers, like GCC, can detect when you make use of a function from the standard C library. In GCC, for example, if you make use of the function printf, the compiler immediately recognizes the function, implicitly includes the header file stdio and generates a warning. It is not good, nor sustainable, to make use of this function, so always include the necessary header files, even if they are part of the C standard.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.