简体   繁体   English

C++中#ifdef和#if的用途是什么

[英]What does purpose use #ifdef and #if in C++

In my project code, I found that someone used #ifdef and #if in code.在我的项目代码中,我发现有人在代码中使用了#ifdef#if I would like to know what does purpose for using them?我想知道使用它们的目的是什么? As my knowledge, it said to the preprocessor will not do anything inside that code.据我所知,它对预处理器说不会在该代码中执行任何操作。 The below code gives two examples for using them.下面的代码给出了两个使用它们的例子。 I tried to find what definition of TEST_PURPOSE (true/false), but it can not find.我试图找到TEST_PURPOSE的定义(真/假),但找不到。 From below code, how to do something inside #ifdef TEST_PURPOSE ?从下面的代码中,如何在#ifdef TEST_PURPOSE中做一些事情? I am using visual studio 2012我正在使用视觉工作室 2012

#ifdef TEST_PURPOSE
    int i=1;
    printf("Something %d,"i);
#endif

#if 0
  int i=1;
  printf("Something %d,"i);
#endif

The meaning of #ifdef is that the code inside the block will be included in the compilation only if the mentioned preprocessor macro is defined. #ifdef的含义是,只有在定义了提到的预处理器宏时,块内的代码才会被包含在编译中。 Similarily #if means that the block will be included only if the expression evaluates to true (when replacing undefined macros that appears in the expression with 0).类似地, #if意味着只有当表达式的计算结果为真时才会包含块(当用 0 替换出现在表达式中的未定义宏时)。

One important point here is that the preprocessor processes the source before it's compiled and if the block is not included it will not be parsed at all by the actual compiler.这里重要的一点是预处理器在编译之前处理源代码,如果不包含该块,则实际编译器根本不会对其进行解析。 This is an important feature of the construct.这是结构的一个重要特征。

Now for some reason C/C++ uses this.现在由于某种原因 C/C++ 使用它。 These languages processes the file in linear order so things that appears further down the source is not yet known and more important things that appears in other source files.这些语言以线性顺序处理文件,因此出现在源代码下方的内容尚不为人所知,而更重要的内容则出现在其他源文件中。 This means that there is no (good) automatic way that a symbol in one source file could be referred to in another source file, especially if you want the type to be correct.这意味着没有(好的)自动方式可以在另一个源文件中引用一个源文件中的符号,特别是如果您希望类型正确。 This means that you will have to have prototypes and extern definitions to be able to refer to these.这意味着您必须拥有原型和extern定义才能引用它们。 Also the case where two source files should share data types ( struct s and enum s) this would have to be done.在两个源文件应该共享数据类型( struct s 和enum s)的情况下,也必须这样做。

In order to make it more practical one would put these inside a header file that each source file could #include (which basically means to insert the header file into what the actual compiler sees).为了使其更实用,可以将它们放在每个源文件都可以#include的头文件中(这基本上意味着将头文件插入到实际编译器看到的内容中)。 This in turn easily leads to the situation where one header file includes another and you may run into the situation where the same file would be included twice.这反过来很容易导致一个头文件包含另一个头文件的情况,您可能会遇到同一个文件被包含两次的情况。 Since it's invalid to repeat struct definitions one would need to make sure that the same header file is not defined twice - that's where the #ifndef comes handy in the include-guard:由于重复struct定义是无效的,因此需要确保相同的头文件没有被定义两次——这就是#ifndef在 include-guard 中派上用场的地方:

#ifndef HEADER_INCLUDED_
#define HEADER_INCLUDED_

// actual payload of the header file

#endif

In addition at a time where the parsing and compilation of the files would take long time this could result in speedup since the payload of the header could quickly be skipped (the preprocessing phase processes the source much faster than the actual compilation phase).此外,在文件的解析和编译需要很长时间的时候,这可能会导致加速,因为可以快速跳过标头的有效负载(预处理阶段处理源代码的速度比实际编译阶段快得多)。

Another reason one "needed" macros are that early C-compilers were likely to just translate the code into assembler rather directly. “需要”宏的另一个原因是早期的 C 编译器可能只是直接将代码翻译成汇编程序。 You could avoid function calls by using macros instead which would result in the expansion of it would be inserted directly at the spot and would generate code right there instead of having to do a function call.您可以通过使用宏来避免函数调用,这会导致它的扩展将直接插入到现场并在此处生成代码,而不必进行函数调用。 The same thing applies to constants which would otherwise be variables that had to be fetched at some other place instead of being placed right into the generated code.同样的事情也适用于常量,否则这些常量是必须在其他地方获取的变量,而不是直接放入生成的代码中。

A third reason is the possibility of conditional compilation.第三个原因是条件编译的可能性。 Most compilers predefine a set of macros that are intended to give information about what system is being compiled for.大多数编译器预定义了一组宏,旨在提供有关正在编译的系统的信息。 We have for example the macro _WIN32 that is only defined if you're compiling for windows.例如,我们有宏_WIN32 ,它仅在您为 windows 编译时才定义。 This would make it possible to have one code snippet that will be included only for windows and another that would be included instead if it's another platform.这将有可能拥有一个仅包含在 windows 中的代码片段,而另一个将包含在另一个平台上的代码片段。 Most compiler also has the possibility to set custom macros from command line which would mean that one could from command line (in visual studio you can change them in the project setting as well) alter which parts that will be compiled.大多数编译器还可以从命令行设置自定义宏,这意味着可以从命令行(在 Visual Studio 中,您也可以在项目设置中更改它们)更改将被编译的部分。 The most striking such macro is the NDEBUG macro which if defined will disable all assert s - it's normal to add a /DNDEBUG when compiling release builds.最引人注目的此类宏是NDEBUG宏,如果定义该宏,它将禁用所有assert s - 在编译发布版本时添加/DNDEBUG是正常的。

#ifdef and #if are pre-processor directives, they are evaluated before the code is even compiled. #ifdef#if是预处理器指令,它们甚至在代码编译之前就被评估。
there are many uses for pre-processor directives, in your example: #ifdef and #if are used to include or exclude certain parts of the code from compiling.在您的示例中,预处理器指令有很多用途: #ifdef#if用于在编译中包含或排除代码的某些部分。

Emphasis : excluded as in does not exist in the build process completely!强调:在构建过程中完全不存在excluded as in!
you can have gibberish in an inactive pre-processor block.您可以在不活动的预处理器块中出现乱码。

Note : #if defined(A) is the same as #ifdef A , so i'll refer to #if only.注意#if defined(A)#ifdef A相同,所以我将仅参考#if

Use 1 - disable processing the same Header file through chain inclusions.使用 1 - 禁用通过链包含处理相同的头文件。

most common use is "header guard":最常见的用途是“头部防护”:
through #include chains you might reenter the same H file and create unforeseen phenomena, therefore, it is very common to use the following construct通过#include链,您可能会重新进入相​​同的 H 文件并创建无法预料的现象,因此,使用以下构造非常常见

#if !defined(MyHeader_H)
#define MyHeader_H

...

#endif

At start, MyHeader_H wont be defined construct, will be processed, including the MyHeader_H ...在开始时, MyHeader_H不会被定义构造,将被处理,包括MyHeader_H ...
in subsequent calls, #ifndef MyHeader_H is false and the H file wont be included in the module.在随后的调用中, #ifndef MyHeader_Hfalse ,并且 H 文件不会包含在模块中。

Use 2 - Define the configuration使用 2 - 定义配置

Some projects have several configurations, lets say using different hardware types or some different behaviors.有些项目有多种配置,比如说使用不同的硬件类型或一些不同的行为。

You can write smth like:你可以这样写:

#if defined(FLASH_TYPE_A)
code to use flash type A
#elif defined (FLASH_TYPE_B)
code to use flash type B
#else 
ASSERT("NO FLASH TYPE DEFINED!");
#endif

in this code, you can use /dFLASH_TYPE_A or /dFLASH_TYPE_B during compilation to define which code will be included...在此代码中,您可以在编译期间使用/dFLASH_TYPE_A/dFLASH_TYPE_B来定义将包含哪些代码...

notice: there is a difference from useing standard if() statement,注意:与使用标准if()语句有区别,
as in this example only one code will be included in the binary.在本例中,二进制文件中只包含一个代码。


there are more uses, but i think these are the most common ones!还有更多用途,但我认为这些是最常见的!

#ifdef means if defined . #ifdef表示如果已定义 If the symbol following #ifdef is defined, either using #define in prior source code or using a compiler command-line argument, the text up to the enclosing #endif is included by the preprocessor and therefore compiled.如果定义了#ifdef之后的符号,无论是在先前的源代码中使用#define 还是使用编译器命令行参数,那么直到封闭的#endif 的文本都被预处理器包含并因此被编译。

#if works similarly, but it evaluates the boolean expression following it. #if的工作方式类似,但它会计算其后的布尔表达式。 If that expression is true, the code up to the enclosing #endif is included.如果该表达式为真,则包含直到封闭的#endif的代码。

These are precompiler directives.这些是预编译器指令。 The C++ precompiler, originally from C (not sure if it is different now or not) allows you to change the text that the compiler will see based on variables that you define or constants.最初来自 C 的 C++ 预编译器(不确定现在是否有所不同)允许您根据您定义的变量或常量更改编译器将看到的文本。

I'm sure you've seen the header guards我敢肯定你见过头球后卫

#ifndef X_H
#define X_H

...

#endif

which prevent the header from being included multiple times.这可以防止标题被多次包含。

These are the same.这些都是一样的。 If you have TEST_PURPOSE defined (by #define TEST_PURPOSE ) you will get that block of code protected by #ifdef TEST_PURPOSE .如果您定义了TEST_PURPOSE (由#define TEST_PURPOSE定义),您将获得受#ifdef TEST_PURPOSE保护的代码块。 The #if 0 will never be included, and is probably for test as well. #if 0永远不会被包括在内,并且可能也用于测试。

#if 0
...
#endif

is one way to exclude a large block of code from being compiled.是从编译中排除一大块代码的一种方法。 It's like a large block of commented out code.这就像一大块被注释掉的代码。

#ifdef TEST_PURPOSE
...
#endif

on the other hand contains code that is included/excluded base on whether the pre-processor macro TEST_PURPOSE is defined or not.另一方面,包含/排除基于预处理器宏TEST_PURPOSE是否定义的代码。

how to do something inside #ifdef TEST_PURPOSE如何在#ifdef TEST_PURPOSE

That's easy: define TEST_PURPOSE .这很简单:定义TEST_PURPOSE Typical places to do so are as command line arguments, modifying a common header, or when appropriate, making the definition before you include a header file this appears in.这样做的典型地方是作为命令行参数,修改公共头文件,或者在适当的时候,在包含出现的头文件之前进行定义。

#ifdef checks whether the name following is #define d before it. #ifdef检查后面的名称是否是它前面的#define d。 The code between the #ifdef and #endif will be ignored if the check fails.如果检查失败, #ifdef#endif之间的代码将被忽略。

The check can be fulfilled by writing #define TEST_PURPOSE explicitly before that #ifdef , or passing /D "TEST_PURPOSE" as an argument to the MSVC compiler.可以通过在#ifdef之前显式编写#define TEST_PURPOSE或将/D "TEST_PURPOSE"作为参数传递给 MSVC 编译器来完成检查。 In the case that you are using Visual Studio, this can be set in the project configuration, so that you can switch it on and off easily.如果您使用的是 Visual Studio,则可以在项目配置中进行设置,以便您可以轻松地打开和关闭它。

can #if be used in C++ the same way used in C? #if 在 C++ 中的使用方式与在 C 中使用的方式相同吗? any difference with respect to C++?与 C++ 有什么不同吗?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM