开发者

Can #include directives go somewhere other than the start of a file (like inside a loop)? [duplicate]

开发者 https://www.devze.com 2023-04-03 02:52 出处:网络
This question already has answers here: Closed 11 years ago. Possible Duplicate: #include anywhere For the respective languages, is the following valid (acceptable programming practice):
This question already has answers here: Closed 11 years ago.

Possible Duplicate:

#include anywhere

For the respective languages, is the following valid (acceptable programming practice):

#include "SomeHeader.h"
#include "HeaderDefs.h" //Includes #defines (like CONST_VAR)

void Function1(){;}
void Function2(){;} //etc
//Additionally:
void Function3(){while(1){
  #include "Files.h"
  ;
}} //Result?    

#include "HeaderUndefs.h" //Includes #undef (like undef CONST_VAR)

In expansion from below comment:

I expanded. Bear in mind it's 'validity' and not 'will it compile'. I am sure it can compile, but Stack Overflow offers insights (like Daniel Wagner'开发者_运维技巧s) that intrigues further exploration. Can I have a while loop of #includes? (Or does this break convention... #includes anywhere - are they valid also?).


Yep, #include directives can go just about anywhere. Even inside functions, or for loops, or anything. The preprocessor that fills that stuff in doesn't know anything about the C (or C++) language, it's totally dumb.


It is valid, but probably has no purpose for CPP files (which I assume yours is, since you have function bodies).

CPP files are not intended to be included in other files, so just undefining macros by #include "HeaderUndefs.h" at the end of CPP won't be seen anywhere. If, however, "HeaderUndefs.h" does something that is meaningful as a part of a CPP file (such as defining functions), it may make sense. This is usually a horrible thing for maintainability, but can be done...


The code you presented is not valid and will not compile. A #include directive, like any other preprocessor directive, must be on a line by itself. There can be arbitrary whitespace (including comments) before the #, between the # and the include, etc., but there can't be any other code (or other directives) on the same line. EDIT: This applied to the original version of the question; it was edited while I was writing this.

If your code is modified so the #include is on a line by itself, it's potentially valid (depending on the contents of the file you're including). But it's not at all a useful thing to do. In particular, #include directives are processed at compile time; putting a #include directive inside a loop does not mean that the file will be included multiple times.

It might make sense to put a chunk of code in a separate file and #include it inside a loop; for example, you might choose which file to include based on some configuration option. But it's an extremely ugly way to structure your code, and whatever you're trying to accomplish, there's almost certainly a cleaner way to do it. (For example, the included file might define a macro that you can invoke inside the loop; you could then have the #include directive at the top of your source file.)

Think of the preprocessor as a power tool with no safety features. Use it with discipline, and you can do useful things with it. Start using it in "clever" ways, and you can lose limbs.


Typically, included files are headers, which contain prototypes, definititions, types, and other data that must be declared/defined BEFORE the code in the file itself, which is why they are at the top. It is rare to have a included file that contains information that is more useful in another place in the file.
Undefs are possible, but seem like they would cause more problems, since the only possible purpose would be to put them in the middle of a compilation unit, which would just be confusing.
A more common usage is .inl files, which are "inline" files, which work like very large macros. The only one I use is a "BitField.inl" I made, which makes a handy bitfield class along with a ToString(...) member, which is used as follows:

#define BITNAME State
#define BITTYPES SEPERATOR(Alabama) SEPERATOR(Alaska) SEPERATOR(Arazona) SEPERATOR(Arkansas) SEPERATOR(California) \
                 SEPERATOR(Colorado) SEPERATOR(Connecticut) SEPERATOR(Delaware) SEPERATOR(Florida) SEPERATOR(Georga) \
                 SEPERATOR(Hawaii) SEPERATOR(Idaho) SEPERATOR(Illinois) SEPERATOR(Indiana) SEPERATOR(Iowa) \
                 SEPERATOR(Kansas) SEPERATOR(Kentucky) SEPERATOR(Louisiana) SEPERATOR(Maine) SEPERATOR(Maryland) \
                 SEPERATOR(Massachusettes) SEPERATOR(Michigan) SEPERATOR(Minnesota) SEPERATOR(Mississippi) SEPERATOR(Missouri) \
                 SEPERATOR(Montana) SEPERATOR(Nebraska) SEPERATOR(Nevada) SEPERATOR(NewHampshire) SEPERATOR(NewJersey) \
                 SEPERATOR(NewMexico) SEPERATOR(NewYork) SEPERATOR(NorthCarolina) SEPERATOR(NorthDakota) SEPERATOR(Ohio) \
                 SEPERATOR(Oklahoma) SEPERATOR(Oregon) SEPERATOR(Pennsylvania) SEPERATOR(RhodeIsland) SEPERATOR(SouthCarolina) \
                 SEPERATOR(SouthDakota) SEPERATOR(Tennessee) SEPERATOR(Texas) SEPERATOR(Utah) SEPERATOR(Vermont) \
                 SEPERATOR(Virginia) SEPERATOR(Washington) SEPERATOR(WestVerginia) SEPERATOR(Wisconsin) SEPERATOR(Wyoming)
#include "BitField.inl"   // WOO MAGIC!

int main() {
     StateBitfield States;
     States.BitField = 0; // sets all values to zero;
     States.Alaska = 1; // activates Alaska;
     std::cout << "States.Bitfield=" << (int)States.BitField << std::endl;  
     //this is machine dependent.
     States.BitField |= (StateBitfield::WashingtonFlag | StateBitfield::IdahoFlag); 
     // enables two more
     std::cout << "CaliforniaFlag=" << (States.BitField & StateBitfield::CaliforniaFlag) << '\n'; 
     // 0, false.
     std::cout << "sizeof(colorBitField)=" << sizeof(colorBitfield) << std::endl;
     // 4, since BITTYPE wasn't defined

     States.BitField = (StateBitfield::AlaskaFlag | StateBitfield::MinnesotaFlag | StateBitfield::FloridaFlag | StateBitfield::NorthDakotaFlag | 
                    StateBitfield::SouthDakotaFlag | StateBitfield::CaliforniaFlag | StateBitfield::OregonFlag| StateBitfield::NevadaFlag | 
                    StateBitfield::IdahoFlag | StateBitfield::MichiganFlag | StateBitfield::OregonFlag| StateBitfield::NevadaFlag);
     // sets the states I've been to
     //for each state, display if I've been there
     for(unsigned int i=0; i<50; i++) {
         //This is showing what is enabled
         if (States.BitField & (1LL << i))
             std::cout << StateBitfield::ToString((StateBitfield::StateBitNum) i) << '\n'; 
     }
     //Shows the states that were flagged
     std::cout << States.Alaska << States.Minnesota << States.Florida << States.NorthDakota << States.SouthDakota << States.California <<
            States.Oregon << States.Nevada << States.Idaho << States.Michigan << States.Oregon << States.Nevada << std::endl;
     //displays 111111111111  (I think I had this in for debugging.)
    }
    States.BitField &= StateBitfield::NoFlags;
    //set all to zero
    States.BitField |= StateBitfield::AllFlags;
    //set all to one
}


You can put an #include directive just about anywhere in the code; that doesn't mean it's a good idea.

I remember having to maintain some code where the author put random snippets of code into header files and #included them where necessary (these weren't self-contained functions, they were just blocks of statements). This made code that was already badly written and hard to follow that much worse.

There's a temptation to use the preprocessor for really sophisticated tasks; resist that temptation.


i think this is valid if you don't use any variable or function from the HeaderUnderfs.h before #include "HeaderUnderfs.h"


/#include is a preprocessor directive. They mean nothing to the actual language, and are valid. To the compiler, those physical files are inserted in-line with the other source.

0

精彩评论

暂无评论...
验证码 换一张
取 消