#include 指令可以放在文件开头以外的地方(例如循环内)吗?

发布于 2024-12-03 13:58:04 字数 708 浏览 0 评论 0原文

可能的重复:
#include 任何地方

对于相应的语言,以下内容是有效的(可接受的编程实践):

#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)

在以下评论的扩展中:

我扩大了。 请记住它是“有效性”,而不是“它会编译吗”。我确信它可以编译,但 Stack Overflow 提供的见解(如 Daniel Wagner 的)激发了进一步的探索。我可以有 #includes 的 while 循环吗? (或者这是否打破了约定......#includes 任何地方 - 它们也有效吗?)。

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?).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

三寸金莲 2024-12-10 13:58:04

是的,#include 指令几乎可以放在任何地方。甚至在函数内部,或 for 循环,或任何东西。填充这些内容的预处理器对 C(或 C++)语言一无所知,它完全是愚蠢的。

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.

简单 2024-12-10 13:58:04

它是有效的,但可能对 CPP 文件没有任何用途(我认为你的文件是这样,因为你有函数体)。

CPP 文件不打算包含在其他文件中,因此在 CPP 末尾通过 #include "HeaderUndefs.h" 取消定义的宏不会在任何地方看到。然而,如果“HeaderUndefs.h”作为 CPP 文件的一部分做了一些有意义的事情(例如定义函数),那么它可能是有意义的。对于可维护性来说,这通常是一件可怕的事情,但可以做到......

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...

杯别 2024-12-10 13:58:04

您提供的代码无效并且无法编译。 #include 指令与任何其他预处理器指令一样,必须单独位于一行。 # 之前、#include 之间可以有任意空格(包括注释),但不能有同一行上的任何其他代码(或其他指令)。 编辑:这适用于问题的原始版本;当我写这篇文章时它被编辑了。

如果您的代码经过修改,使 #include 单独位于一行,则它可能有效(取决于您所包含的文件的内容)。但这根本不是一件有用的事情。特别是,#include 指令是在编译时处理的;将 #include 指令放入循环内并不意味着该文件将被包含多次。

将一段代码放在单独的文件中并#include 将其放入循环中可能是有意义的;例如,您可以根据某些配置选项选择要包含的文件。但这是一种极其丑陋的构建代码的方式,无论你想要实现什么目标,几乎肯定有一种更简洁的方法来实现它。 (例如,包含的文件可能定义一个可以在循环内调用的宏;然后您可以在源文件的顶部添加 #include 指令。)

将预处理器视为一个强大的工具没有安全功能的工具。严格使用它,你可以用它做有用的事情。开始以“聪明”的方式使用它,你可能会失去四肢。

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.

坠似风落 2024-12-10 13:58:04

通常,包含的文件是标头,其中包含原型、定义、类型和其他必须在文件本身的代码之前声明/定义的数据,这就是它们位于顶部的原因。包含的文件很少包含在文件中其他位置更有用的信息。
Undef 是可能的,但似乎它们会导致更多问题,因为唯一可能的目的是将它们放在编译单元的中间,这只会令人困惑。
更常见的用法是 .inl 文件,它们是“内联”文件,其工作方式类似于非常大的宏。我唯一使用的是我制作的“BitField.inl”,它创建了一个方便的位字段类以及一个 ToString(...) 成员,其使用方式如下:

#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
}

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
}
盛夏已如深秋| 2024-12-10 13:58:04

您可以在代码中的任意位置放置 #include 指令;这并不意味着这是一个好主意。

我记得必须维护一些代码,其中作者将随机代码片段放入头文件中,并在必要时使用 #include 它们(这些不是独立的函数,它们只是语句块)。这使得本来就写得很糟糕且难以遵循的代码变得更糟。

人们很容易将预处理器用于真正复杂的任务; 抵制这种诱惑。

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.

拍不死你 2024-12-10 13:58:04

我认为如果您不使用 HeaderUnderfs.h 中的任何变量或函数,这是有效的
#include“HeaderUnderfs.h”之前

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

反目相谮 2024-12-10 13:58:04

/#include 是一个预处理器指令。它们对实际语言没有任何意义,并且是有效的。对于编译器来说,这些物理文件将与其他源一起插入。

/#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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文