Understanding #include in C Language: A Guide to Header Files

#includeIn C language, #include is a preprocessor directive that is used to include the contents of another file into the current file before compilation. In simple terms, it acts like copying and pasting the contents of the specified file at the location of#include.Its core function is toinclude header files, allowing the code to access functions, variables, macros, or type declarations defined externally.

Basic Usage

#include <filename>    // Used to include system standard header files#include "filename"    // Used to include user-defined header files

Key Details

1. Preprocessor Behavior:

  • Before formal compilation, the preprocessor directly copies the contents of the file specified by #include into the current file.

  • For example: #include <stdio.h> will insert the declarations of the standard input-output library (such as the printf() function) into the code.

2. Difference Between Two Forms:

  • #include <file>:

It searches for the file in the system header file directories (e.g., /usr/include) first.

Used to include standard libraries (e.g., stdio.h, stdlib.h).

  • #include “file”:

It searches for the file in the current project directory first, and if not found, then searches the system directories.

Used to include user-defined header files (e.g., #include “myheader.h”).

3. Typical Uses:

  • Using standard library functions (e.g., input/output, mathematical calculations):

c

#include <stdio.h>  // Includes printf()/scanf()#include <math.h>   // Includes sqrt()/sin()

Introducing custom declarations:

c

#include "myfunctions.h" // Includes custom function declarations

4. Contents of Header Files:

Typically includes:

Function declarations (e.g., void printMessage();)

Macro definitions (e.g., #define PI 3.14)

Type definitions (e.g., typedef struct { … } Point;)

External variable declarations (e.g., extern int globalVar;)

Example Analysis

Assuming there are two files:

c

// math_utils.h (header file)int add(int a, int b); // Function declaration// main.c (source file)#include <stdio.h>#include "math_utils.h"  // Inserts the contents of math_utils.hint main() {    int sum = add(10, 20); // Uses the function declared in the header    printf("Sum: %d\n", sum); // Uses printf from stdio.h    return 0;}// math_utils.c (function implementation)int add(int a, int b) {     return a + b; }

During compilation, the preprocessor will copy the contents of stdio.h and math_utils.h into main.c, allowing the compiler to recognize the declarations of printf and add.

Considerations

Avoiding Duplicate Inclusions:

Use header guards to prevent multiple inclusions:

c

// myheader.h#ifndef MYHEADER_H#define MYHEADER_H/* Header file contents */#endif

Or use #pragma once (a compiler extension, not part of the C standard but widely supported).

Do not add a semicolon:

#include is a preprocessor directive and should not end with a semicolon (e.g., #include <file>; ❌).

Summary

#include is the foundation of modular programming in C language, enabling code reuse through separation of declaration and implementation. Understanding how it works is crucial for managing project dependencies and avoiding compilation errors.

Q.I only defined the _test_pic variable in st7789p3.h, but in the main file and other .c files, I included#include“01Abstract/st7789p3.h”, will this cause a variable redefinition?

Problem Analysis

When you defined the _test_pic variable in the header file st7789p3.h:

c

// st7789p3.hconst uint16_t _test_pic[320*240] = { /* data */ };

Then included this header file in multiple source files:

c

// main.c#include "st7789p3.h"  // Includes _test_pic definition
// st7789p3.c#include "st7789p3.h"  // Also includes _test_pic definition

This will lead to:

The compiler generates one instance of _test_pic when compiling main.c

The compiler generates another instance of _test_pic when compiling st7789p3.c

The linker finds two global variables with the same name and reports a “multiple definition” error.

Correct Solution

st7789p3.h (only contains declaration)

#ifndef ST7789_H#define ST7789_H// Use extern to declare but not defineextern const uint16_t _test_pic[320*240];// Screen size definitions#define ST7789_WIDTH  320#define ST7789_HEIGHT 240// ... other code ...#endif

st7789p3.c (contains actual definition)

c

#include "st7789p3.h"// Actual definition of the image arrayconst uint16_t _test_pic[320*240] = {    // Image data    0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,     // ... complete 76800 elements};// ... other function implementations ...

main.c (only needs to include the header file)

#include "st7789p3.h" // Only includes declarationint main(void) {    // Use the image    ST7789_DrawFullScreenImage(_test_pic);}

Why is defining variables in header files a bad practice?

Violating ODR (One Definition Rule):

The C language requires that global variables can only have one definition

Violating this rule when the header file is included in multiple source files

Memory Waste:

Each source file that includes the header file will create its own copy

For large image data, this can quickly exhaust Flash space

Difficult Maintenance:

Modifying data requires recompiling all source files that include the header file

Increases compilation time

Leave a Comment