#define XYZ before #include precompiled header
Asked Answered
B

1

5

I am refactoring some existing software and I regularly see this

#define XYZ 
#include "stdafx.h"

where stdafx is the precompiled header file.

Q1. Can a knowledgeable person please confirm the following?
That (except perhaps for the file stdafx.cpp) the correct order is always

#include "stdafx.h"
#define XYZ 

My reasoning is as follows. A define before the precompiled header can't affect the precompiled header even if 'used' inside the header, since the header is precompiled. The precompiled header will have used whatever the macro XYZ was set to when the initial compilation took place.

So

#define XYZ 
#include "stdafx.h"

misleads a reader into thinking XYZ may have an influence on the contents of stdafx.h.

Q2. Whether the two are functionally equivalent and my refactoring is safe?

#include "stdafx.h"
#define XYZ 

clearly defines XYZ whereas the alternative does not so clearly define it. (Using the precompiled header might well overwrite the definition with some compilers, for all I know.) Yet defining XYZ before including the precompiled header does seem to work, as it is present so often in the code I am refactoring.

Q3. Is the behaviour defined in a standard?

If I were the compiler writer, I would reject any #define prior to inclusion of a precompiled header! My VS2019 doesn't.

Berners answered 2/7, 2019 at 11:48 Comment(9)
for Q3: I dont use vs, but it would find it a major annoyance if it would behave the way you want. Its not the compilers job to tell me in what order I should put my includes / definesChristman
@formerlyknownas_463035818 well if you have written something that can't work correctly, at least a warning would be more than welcome.Comber
My project compiled about 10% faster without precompiled headers for a full build, and often hundreds of times faster for an incremental build. (The latter due to misuse of precompiled headers.)Aparri
@Comber warnings can be acknowledged and then ignored, but if a compiler would reject code because of this I would want to use a different oneChristman
@formerlyknownas_463035818: All compilers that support C++ precompiled headers must necessarily work like this. Precompiled headers can contain C++ templates, which are compile-time Turing-complete. You can't precompile those for any given input (i.e. other code preceding the pre-compiled header)Houk
@Houk not sure what you are refering to. How is what you are saying related to a compiler rejecting code that has a #define before a precompiled header is included?Christman
@Houk I mean as I understand the answer, the define cannot have any impact on the precompiled header anyhow, so why should it be forbidden?Christman
@formerlyknownas_463035818: Because the semantics differ between compilers using precompiled headers and those that don't.Houk
@Houk ah ok, I think now I get it. Thanks for your patience :)Christman
P
6

You state:

A define before the precompiled header can't affect the precompiled header even if 'used' inside the header, since the header is precompiled.

But from the Microsoft documentation Precompiled Header Files:

[#defines] Must be the same between the compilation that created the precompiled header and the current compilation. The state of defined constants is not checked, but unpredictable results can occur if your files depend on the values of the changed constants.

Polyclitus answered 2/7, 2019 at 11:50 Comment(3)
Which makes sense knowing their implementation - a precompiled header contains almost all of the internal state of the compiler at the end of stdafx.cpp, minus such obvious ones as the __FILE__ and __LINE macro's. #include "stdafx.h" overwrites the corresponding compiler state. It's not really feasible to merge such state. Hence, a preceding #define XYZ is lost.Houk
You might want to make it clear that the first quote is part of my question rather than a statement by Microsoft. I believe the second quote is about the compiler define option -D, e.g. -DXYZ=TRUE, but it may well apply to #define as well, especially the unpredicitable results that my refactoring aims to avoid.Berners
To clarify: when 2 neighbor CPP files both "#include "stdafx.h", can they have different #define's (which would switch a condition in those includes) before this include ? Thus is the PCH somehow effective per source file? ( replayed? fixed state ...? )Ordain

© 2022 - 2024 — McMap. All rights reserved.