Firstly, the primary purpose of include guards is to prevent something from being declared twice in the same translation unit. The "in the same translation unit" part is the key here. Your experiment with two different translation units has nothing to do with the purpose of include guards. It does not demonstrate anything. It is not even remotely related.
In order to take advantage of include guards you have to include (explicitly or implicitly) the same header file twice into one implementation file.
Secondly, just because some header file has no include guards and just because you included that header file twice into the same translation unit does not mean that it will necessarily trigger errors. In order to lead to errors the header must contain declarations of specific "non-repeatable" kind. No every header contains such offending declarations. Not every declaration is offending in this sense.
Your bar.h
(as posted) is actually harmless. Formally, you don't need include guards in your bar.h
. It has a single function declaration, which can be repeated many times in one translation units. So, including this header multiple times will not lead to errors.
But add something like that to your bar.h
struct SomeStruct
{
int i;
};
and then just include it twice in the same implementation file, and you will end up with an error. This error is what include guards are intended to prevent. The language prohibits repeating full declarations of the same struct type in the same translation unit.
Include guards are typically placed in header files unconditionally. They are, I'm quite sure, present inside <stdio.h>
and <string.h>
as well. It is unclear why you claim that these headers "were included without an include guard". Did you check inside these files? In any case, again, your experiment with two different translation units does not demonstrate anything relevant anyway.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…