Search code examples
cincludec-preprocessor

C Preprocessor include directive


When I include another source(I.e stdio.h) the preprocessor is smart enough to include only the functions that I am using in my code?

Example: Assuming this small program, would be ease to include only what I am using, and what the printf functions uses, including them recursively, but what about bigger programs?

#include <stdio.h> 

int main(void) {
   printf("Hello World\n"); 
   return 0;
}

Solution

  • No. On the contrary:

    #include performs textual replacement: it opens the file and copies all1 of its contents into your main C file. In the process it executes all preprocessor instructions in the included file. Amongst other things, this means that it will recursively include all files that are #included in the header.

    #include does not know and does not care which part of the included file you end up using.


    1 As mentioned, preprocessor instructions are executed in the included file. This can modify what gets included. For example, assume the following header file header.h:

    #ifndef HEADER_H
    #define HEADER_H
    
    #ifdef NDEBUG
    #  define LOG(...) ((void) 0)
    #else
    #  define LOG(...) log_message(__FILE__, __LINE__, __VA_ARGS__)
    
    inline void log_message(const char* filename, int line, ...) {
        // Logging code omitted for brevity.
    }
    #endif
    
    // other stuff
    
    #endif
    

    Now, if your main.c file looks as follows:

    #define NDEBUG
    #include "header.h"
    
    int main(void) {
        // …
        LOG("hello");
    }
    

    … then, after preprocessing, your main.c file would looks something like this (I’m omitting some irrelevant stuff):

    # 1 "main.c"
    
    # 1 "./header.h" 1
    
    
    
    
    # 13 "./header.h"
    
    // other stuff
    
    
    # 3 "main.c" 2
    
    int main(void) {
        // …
        ((void) 0);
    }
    

    … in other words, only the part of header.h that corresponds to #ifdef NDEBUG was included, not the part in the #else clause. If we had included header.h without defining NDEBUG, then the included header code would have contained the definition of log_message.