Conditional compilation in C#if, #elif, #else, #endif, #ifdef, #ifndef

Some programs may want to generate a different software by simply setting some parameters in the case of debugging, compatibility, platform porting, etc. Of course, you can set variables and write all the possible codes in it. When initializing Configuration, but in different situations, only a part of the code may be used, and there is no need to write all the code, you can use conditional compilation, set the compilation conditions through the precompiled instructions, and compile different codes when different needs are needed.

   (1) Conditional compilation method

   Conditional compilation is achieved through precompiled instructions. The main methods are:

   1、#if, #elif, #else, #endif

 #if 条件 1
 代码段 1
#elif 条件 2
   代码段 2
...
#elif 条件 n
 代码段 n
#else
 代码段 n+1
#endif

  That is, different conditions can be set, and different codes can be compiled at compile time. The expressions in the precompiled instructions are basically the same as the expressions of the C language itself, such as logical operations, arithmetic operations, bit operations, etc. All can be used in the precompiled instructions. The reason why conditional compilation can be achieved is that precompiled instructions are processed before compilation, macro replacement is performed through precompilation, code segments are conditionally selected, and then the final code to be compiled is generated, and finally compiled.

   The general meaning of #if is that if the constant expression behind #if is true, the code it controls is compiled, such as code segment 1 when condition 1 is established, and condition 2 is not established if condition 1 is established. If condition 2 is established Then compile the code segment 2, otherwise judge other conditions by analogy, if the conditions 1-N fail, compile the final code segment n+1.

   2、#ifdef, #else, #endif或#ifndef, #else, #endif

  Another way to conditionally compile is to use the #ifdef and #ifndef commands, which mean "if defined" and "if not defined", respectively. Defined refers to whether there is a macro defined by the #define instruction when compiling this code. The #ifndef instruction means that a macro defined by #define cannot be found. The macro can be in the current file. It can also be defined in other files, but included in this file before this directive.

The general form of #ifdef is:

 #ifdef macro_name
    代码段 1
#else
    代码段 2
#endif


#ifdef的一般形式是:

#ifndef macro_name
    代码段 2
#else
    代码段 1
#endif

   The effect of these two pieces of code is exactly the same.

   3. Through the macro function defined (macro_name)

  The parameter is the macro name (no need to add ""). If the macro_name is defined, it will return true, otherwise it will return false. With this function, you can write more complex conditional compilation instructions such as

 #if defined(macro1) || (!defined(macro2) && defined(macro3))
...
#else
...
#endif

   (2) Conditional compilation techniques and examples

   (1) #ifdef and #defined() comparison

  First compare these two methods. The first method can only judge one macro. If the condition is more complicated, it will be more troublesome to implement, and the latter is more convenient. If there are two macros MACRO_1, MACRO_2 will compile code segment A only if both macros are defined. The implementations are as follows:

 #ifdef MACRO_1
#ifdef MACRO_2
    代码段 A
#endif
#endif

或者
#if defined(MACRO_1) && defined(MACRO_2)
#endif

  Similarly, it is more troublesome to use #ifdef to implement more complex conditions, so it is recommended to use the latter, because even if the current code uses simple conditional compilation, it may increase in maintenance and upgrades in the future, and the latter is more maintainable. . Older compilers may not implement the #defined() directive, C99 has been added as standard. For compatibility with older compilers, the #ifdef directive is also required.

   2. Compare #if with #ifdef or #if defined()

   For example, I wrote a printf function myself, and I want to achieve conditional compilation through a macro MY_PRINTF_EN, which can be achieved with #if as follows

Conditional compilation in C language.#define MY_PRINTF_EN 1
#if MYS_PRINTF_EN == 1
 int printf(char* fmt, char* args, ...)
{
    ...
}
#endif

  If the macro MY_PRINTF_EN is defined as 1, then compile this code, if the macro definition is not 1 or the macro is not defined, this code is not compiled. The same can also be achieved by #ifdef or #defined(), such as

 #define MY_PRINTF_EN 1

#if defined(MY_PRINTF_EN)
 int printf(char* fmt, char* args, ...)
{
    ...
}
#endif

  In this case, the two methods have the same purpose, but imagine if you write two printf functions in order to save code, and use different printf functions in different situations, one is the compact version and the other is the full-featured standard version, such as:

 #define MY_PRINTF_SIMPLE

#ifdef MY_PRINTF_SIMPLE
   void printf(*str) // 向终端简单地输出一个字符串
{...
}
#endif
#ifdef MY_PRINTF_STANDARD
 int printf(char* fmt, char* args, ...)
{...
}
#endif

同样可以用#if defined()实现
#define MY_PRINTF_SIMPLE

#if defined(MY_PRINTF_SIMPLE)
   void printf(*str) // 向终端简单地输出一个字符串
{
    ...
}
#elif defined(MY_PRINTF_STANDARD)
 int printf(char* fmt, char* args, ...)
{
    ...
}
#endif

  Both methods can be implemented, but the latter is obviously more convenient. But imagine if you have three versions, it is more troublesome to use the former, but the method is similar, it is more convenient to use the latter, but it still needs three macros to control, you need to live in three macros, you can use #if to improve it. A macro directly controls N situations such as:

 #define MY_PRINTF_VERSION     1

#if MY_PRINTF_VERSION == 1
   void printf(*str) // 向终端简单地输出一个字符串
{
    ...
}
#elif MY_PRINTF_VERSION == 2
 int printf(char* fmt, char* args, ...)
{
    ...
}
#elif MY_PRINTF_VERSION == 3
int printf(unsigned char com_number, char* str)
{
    ...
}
#else
    默认版本
#endif

   In this way, you only need to modify the number to complete the version selection

   It seems that it is better to use #if, imagine the following situation: you write a configuration file called config.h to configure some macros, and control the code through these macros, such as your macros in config.h

   #define MY_PRINTF_EN 1

   To control whether you need to compile your own printf function, there are the following instructions in your source code file printf.c

 #i nclude "config.h"
#if MY_PRINTF_EN == 1
 int printf(char* fmt, char* args, ...)
{
    ...
}
#endif

  But this will also have a problem, that is, if you forget to add the macro MY_PRINTF_EN in config.h, the printf function written by yourself will not be compiled, and some compilers will give a warning: MY_PRINTF_EN is undefined. If you have two versions and want to have a default version, you can do this in printf.c

 #incldue "config.h"
#if !defined(MY_PRINTF_VERSION)
  #define MY_PRINTF_VERSION   1
#endif

#if MY_PRINTF_VERSION == 1
   void printf(*str) // 向终端简单地输出一个字符串
{
    ...
}
#elif MY_PRINTF_VERSION == 2
 int printf(char* fmt, char* args, ...)
{
    ...
}
#elif MY_PRINTF_VERSION == 3
int printf(unsigned char com_number, char* str)
{
    ...
}
#endif

 这种情况下还得用到#ifdef或#if defined(),你可以不用动主体的任何代码,只需要修改printf.c文件中MY_RPINTF_VERSION宏的数字就可以改变了,如果用前面那种方法还得拖动代码,在拖动中就有可能造成错误。

   Think about it again, if the software is upgraded, or there are major changes, there were originally three versions, and now there are only two versions left, such as

 #if MY_PRINTF_VERSION == 2
 int printf(char* fmt, char* args, ...)
{
    ...
}
#elif MY_PRINTF_VERSION == 3
int printf(unsigned char com_number, char* str)
{
    ...
}
#endif

  Because the core code doesn't want the people who use it to care, they just need to modify the config.h file, and then make it compatible in printf.c. If someone previously configured the macro MY_PRINTF_VERSION to 1 in config.h, that is

   #define MY_PRINTF_VERSION   1

   And now there is no version 1, what should I do if I want to be compatible? That can of course be achieved with more complex conditions such as:

 #if MY_PRINTF_VERSION == 2 || MY_PRINTF_VERSION == 1
 int printf(char* fmt, char* args, ...)
{
    ...
}
#elif MY_PRINTF_VERSION == 3
int printf(unsigned char com_number, char* str)
{
    ...
}
#endif

   But there is another way, which is to use the #undef command

 #if MY_PRINTF_VERSION == 1
  #undef MY_PRINTF_VERSION
  #define MY_PRINTF_VERSION  2
#endif
#if MY_PRINTF_VERSION == 2
 int printf(char* fmt, char* args, ...)
{
    ...
}
#elif MY_PRINTF_VERSION == 3
int printf(unsigned char com_number, char* str)
{
    ...
}
#endif

 

   There is another advantage of using #if. If you remember the macro name incorrectly and define MY_PRINTF_EN as MY_PRINT_EN, then the code you control with #ifdef MY_PRINTF_EN or #if defined(MY_PRINTF_EN) cannot be compiled, and it is not good to check Check, it is easy to check with #if MY_PRINTF_EN == 1, because you define MY_PRINTF_EN as MY_PRINT_EN, then MY_PRINTF_EN is actually not defined, then the compiler will give a warning #if MY_PRINTF_EN == 1 MY_PRINTF_EN is not defined, but It's faster to be wrong.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325443187&siteId=291194637