How are circular #includes allowed?

In c, we can say that we have 2 files

1.h

#include<2.h>

blah blah

and we have 2.h

#include<1.h>

code

How is this allowed?

+3
source share
4 answers

Usually you protect your include file with ifndef / define, which matches the file name. This will not prevent re-inclusion of the file, but it prevents the use of content (inside ifndef) and re-inclusion of recursive inclusion.

 #ifndef HEADER_1_h
 #define HEADER_1_h

 #include "2.h"

 /// rest of 1.h

 #endif

 #ifndef HEADER_2_h
 #define HEADER_2_h

 #include "1.h"

 //  rest of 2.h

 #endif
+15
source

Well, for the sake of completeness, I will start by quoting tvanfosson's answer:

You must use the included guards:

// header1.hpp
#ifndef MYPROJECT_HEADER1_HPP_INCLUDED
#define MYPROJECT_HEADER1_HPP_INCLUDED

/// Put your stuff here

#endif // MYPROJECT_HEADER1_HPP_INCLUDED

However, the inclusion of guards is not intended to solve problems with cyclic dependencies, they are designed to prevent multiple inclusions, which is completely different.

          base.h
        /        \
    header1.h  header2.h
        \        /
         class.cpp

( ) , base.h , , .

, ... , !!

, :

  • "header1.hpp" > , include guard
  • "header2.hpp
  • "header1.hpp", , .
  • "header2.hpp", , "header1.hpp", ( )
  • "header1.hpp", "header2.hpp" - , , , ,

, , , , .

, - .

  • ,
  • "header1.h" : , 2, , header2

(), , .

+7

, "" ( ). :

1.h:

#ifndef HEADER_1_h
#define HEADER_1_h
#include "2.h"

#define A 1
#define B 2

#endif // HEADER_1_h

2.h:

#ifndef HEADER_2_h
#define HEADER_2_h
#include "1.h"

#if (A == B)
#error Impossible
#endif

#endif // HEADER_2_h

main.c:

#include "1.h"

"Impossible" , "2.h" "1.h" - , A B 0. , .

A B "common.h", "1.h", "2.h".

0

++, c, , ++. ++ #pragma once:

1.h:

#pragma once
#include "2.h"
/// rest of 1.h 

2.h:

#pragma once
#include "1.h"
/// rest of 2.h 

. :

  • pragma , , include guard.

  • Some compilers know errors related to C # pragma once. Although most, if not all modern compilers will handle it correctly. For a detailed list, see Wikipedia.

Edit: I think that the directive is also supported in c compilers, but I have never tried it, and besides, in most programs that I have seen, enabling guards is standard (perhaps due to compiler limitations that control the pragma once directive? )

-1
source

Source: https://habr.com/ru/post/1751966/


All Articles