How to prevent header files from being repeatedly included and nested included (transfer)

[From]  http://hi.baidu.com/zengzhaonong/blog/item/8a8871062d481f7f03088106.html

One disadvantage of #include files is that a header file may be included multiple times. To illustrate this error, consider the following code:

#include "xh"
#include "xh"

Obviously, the file xh is included twice, and no one will deliberately write such code. But the following code:
#include "ah"
#include "bh" does

not seem to be a problem. If both ah and bh include a header file xh. Then xh is also included twice here, but its form is not so obvious.

Multiple inclusions appear in large programs in most cases, and it often requires the use of many header files, so it is not easy to find repeated inclusions. To solve this problem, we can use conditional compilation. If all the header files are written like this:
#ifndef _HEADERNAME_H
#define _HEADERNAME_H

...//(header file content)

#endif

then the danger of multiple inclusions is eliminated. When the header file is included for the first time, it is processed normally, and the symbol _HEADERNAME_H is defined as 1. If the header file is included again, through conditional compilation, its content is ignored. The symbol _HEADERNAME_H is named according to the file name of the included header file to avoid conflicts caused by other header files using the same symbol.
 

However, you must remember that the preprocessor still reads the entire header file, even if all the contents of the header file will be ignored. Since this processing will slow down the compilation speed, if possible, multiple inclusions should be avoided.

The use of #ifndef in test-1.0 only prevents the header file from being repeatedly included (in fact, there is only one header file in this example, and there is no problem of repeated inclusion), but it cannot prevent the variable from being repeatedly defined.

# vi test.c
-------------------------------
#include <stdio.h>
#include "test.h"

extern i;
extern void test1();
extern void test2();

int main()
{    test1();    printf("ok/n");    test2();    printf("%d/n",i);    return 0; } # vi test.h ------------------------------- #ifndef _TEST_H_ #define _TEST_H_ char add1[] = "www.shellbox.cn/n"; char add2[] = "www.scriptbox.cn/n"; int i = 10; void test1(); void test2();
























-------------------------------
#include <stdio.h>
#include "test.h"

extern char add1[];

void test1()
{
   printf(add1);
}



# vi test2.c
-------------------------------
#include <stdio.h>
#include "test.h"

extern char add2[];
extern i;

void test2()
{
   printf(add2);
   for (; i > 0; i--) 
       printf("%d-", i);
}



# Makefile
-------------------------------
test:    test.o test1.o test2.o
test1.o: test1.c
test2.o: test2.c
clean:
   rm test test.o test1.o test2.o


错误:
The "multiple definition of" error will appear after test-1.0 is compiled.

Error Analysis:
As each .c file in the project are independent interpretation, even if there is a header file
#ifndef _TEST_H_
#define _TEST_H_
....
#enfif
in other documents as long as it will contain the independent interpretation global.h , And then each .c file generates an independent identifier. When the compiler is linked, it will integrate all the symbols in the project. Because there are variables with the same name in the file, there will be a duplicate definition error.

Solution
Declare variables in the .c file, and then create a header file (.h file) to add extern before all the variable declarations. Be careful not to initialize the variables here. Then include the .h file in other .c files that need to use global variables. The compiler will generate an object file for .c, and then when linking, if the .c file uses global variables, the linker will link to this .c file.






test-2.0

# vi test.c
-------------------------------
#include <stdio.h>
#include "test .h"

int i = 10;
char add1[] = "www.shellbox.cn/n";
char add2[] = "www.scriptbox.cn/n";
extern void test1();
extern void test2();


{
   test1();
   printf("ok/n");
   test2();
   printf("%d/n",i);
   return 0;
}


# vi test.h
-------------------------------
#ifndef _TEST_H_
#define _TEST_H_

extern i;
extern char add1[];
extern char add2[];

void test1();
void test2();

#endif



# vi test1.c
-------------------------------
#include <stdio.h>
#include "test.h"

void test1()
{
   printf(add1);
}


# vi test2.c
-------------------------------
#include <stdio.h>
#include "test.h"

void test2()
{
   printf(add2);
   for (; i > 0; i--) 
       printf("%d-", i);

}

 Two, link indicator: extern

If you want to call functions written in other programming languages ​​(especially C), you must tell the compiler to use different requirements when calling the function. For example, when such a function is called, the order of the function name or parameter arrangement may be different. Whether it is a C++ function calling it, or calling it with a function written in another language. The
    programmer uses a linkage directive to tell the compiler that the function is written in another programming language. The

    linkage directive has two forms :
    Single statement (single statement) form
    Compound statement (compound statement) form

    When #include is included in the parentheses of the compound statement link indicator, the function declarations in the header file are assumed to be in the programming language of the link indicator Written. The

    link indicator cannot appear in the function body.

vi externC.cpp
--------------------------------- ----
#include <iostream>
extern "C" double sqrt(double);
int main()
{     using std::cout;     using std::endl;     double result = sqrt(25);     cout << "result = "<< result << endl;     return 0; } g++ externC.cpp









     If we want C++ functions to be used by C programs, we can also use the extern "C" link indicator to make C++ functions available to C programs.






    As an object-oriented language, C++ supports function overloading, while procedural language C It is not supported. The name of the function in the symbol library after being compiled by C++ is different from that of the C language. For example, suppose the prototype of a function is:
    void foo(int x, int y); the name of 

    the function in the symbol library after being compiled by the C compiler is _foo, and the C++ compiler will generate something like _foo_int_int name. Names such as _foo_int_int contain the function name and the number of function parameters and type information. C++ relies on this mechanism to implement function overloading.

    In order to achieve mixed programming of C and C++, C++ provides the C link exchange designated symbol extern "C" to solve the problem of name matching. After adding extern "C" before the function declaration, the compiler will use the C language The function is compiled into _foo, so that C++ functions can be called in C language.





cppExample.h
-----------------------------------
#ifndef CPP_EXAMPLE_H
#define CPP_EXAMPLE_H
//extern "C "Limited functions or variables are first of the extern type; extern is a keyword in the C/C++ language that indicates the scope (visibility) of functions and global variables. This keyword tells the compiler that the declared functions and variables can be in this Used in modules or other modules.
//Variables and functions modified by extern "C" are compiled and linked according to C language;
extern "C"
//extern int add(int x, int y);
#endif



cppExample.cpp
-----------------------------------
#include "cppExample.h"

int add( int x, int y )
{
    return x + y;
}



cFile.c
-----------------------------------
#include <stdio.h>
//这样会编译出错
//#include "cppExample.h"

extern int add(int x, int y);

int main(int argc, char* argv[])
{
    printf("%d/n", add(2, 3));
    return 0;
}



-----------------------------------

gcc cFile.c cppExample.cpp

 Three, the difference between variable definition and declaration

 In our program design, we use variable definitions and variable declarations all the time, but sometimes we are not very clear about this concept. We know how to use it, but I don’t know how it is. The difference between them is introduced as follows:


    There are two situations for variable declaration:
    (1) One is the need to establish storage space (definition, declaration). For example: int a has already established storage space when it is declared. 
    (2) The other is that no storage space is required (declaration). For example: extern int a where the variable a is defined in another file.
    The former is a "defining declaration" or "definition", and the latter is a "referncing declaration". From a broad perspective, declarations contain definitions, but not all declarations are definitions, for example: int a is both a declaration and a definition. However, for extern a, it is only a declaration, not a definition. Under normal circumstances, we often describe this way, calling the statement that establishes a space as a "definition", and calling the statement that does not need to establish a storage space as a "declaration". Obviously, the declarations we are referring to here are relatively narrow in scope, that is, non-defining declarations.

For example: in the main function 
int main()
{     extern int A; //This is a declaration rather than a definition. The declaration A is an external variable                   that has already been defined. //Note: When declaring an external variable, you can remove the variable type such as: extern A;     dosth(); //execute function } int A; //is the definition, which defines A as an integer external variable (global variable) 








    The "definition" of external variables (global variables) is not the same as the "declaration" of external variables. The definition of external variables can only be done once, and its location is outside all functions, and the external variable declarations in the same file It can be multiple times, and it can be inside the function (declare in which function you want to use) or outside the function (before the point of definition of external variables). The system allocates storage space according to the definition of external variables (rather than the declaration of external variables). For external variables, initialization can only be done in the "definition", not in the "declaration". The so-called "declaration", its function is to declare that the variable is an external variable that has been defined later, and it is just a "declaration" for "quoting" the variable in advance. extern only makes declarations, not definitions. 

    The use of static to declare a variable has two functions:
    (1) For a local variable to be declared with static, the space allocated for the variable will always exist during the execution of the entire program
    (2) The external variable is declared with static, then The function of this variable is limited to this file module

Guess you like

Origin blog.csdn.net/hn_tzy/article/details/104394690