Conditional compilation in C

  • 2020-05-19 05:17:37
  • OfStack

In general, we want the program to execute selectively, often using branch statements such as if-else or switch-case. Sometimes, however, a branch may not execute at all while the program is running.

For example, we will write a cross-platform project that can run under either Windows or Linux. At this time, if we use if-else, it is as follows:

Windows has its own macro _WIN32, and Linux has its own macro s s 16en__


if(_WIN32)
  printf("Windows Executes the following code \n");
else if(__linux__)
  printf("Linux Executes the following code \n");
else
  printf(" Unknown platform cannot run !\n");

There are two problems with this code: 1. S = s = s = s = s = s = s = s = s = s = s = s = s = s = s = s = s = s = s = s = s 2. Assuming that this program can be run, the code of the other two branches will not run at all under Windows, and the same is true under Linux.

We can handle this situation by using conditional compilation. Conditional compilation, just as its name implies, is based on 1 set of conditions for selective compilation, we want to achieve effect, is the other two branches in Windows environment statement doesn't compile, so the generated executable file, also won't have corresponding statement's machine code, improve the efficiency of the compiled already so, at the same time reduce the volume of the executable file.

Conditional compilation can usually be implemented in three ways:

1, #if--#elif--#else--#endif statement implementation

The code implemented by this method is:


#if(_WIN32)
  printf("Windows Executes the following code \n");
#elif (__linux__)
  printf("Linux Executes the following code \n");
#else
  printf(" Unknown platform cannot run !\n");
#endif

It is important to note when using this method that the macro is defined as real #if before it is executed, i.e. :

If there is a macro definition #define _WIN32 0 then #if will not be executed. It needs to be defined as #define _WIN32 for 1 to execute

2, through the #ifdef--#else--#endif statement

The code implemented in this way is


#ifdef(_WIN32)
  printf("Windows Executes the following code \n");
#else
  printf("Linux Executes the following code \n");
#endif

This method only needs to define _WIN32, it doesn't have to be true, that is to say

The #ifdef statement above #define _WIN32 0 can also be executed if there is a macro definition, and even the #ifdef statement above #define _WIN32 can be run

You can also add the #elif statement from method 1


#ifdef(_WIN32)
  printf("Windows Executes the following code \n");
#elif (__linux__)
  printf("Linux Executes the following code \n");
#else
  printf(" Unknown platform cannot run !\n");
#end

However, it should be noted that in this case the value must be true in order for the #elif statement to execute s s 76en__. (also not defined _WIN32)

3. Use the #ifndef statement, which is similar to the second one. ifndef is to execute if no macros are defined.

In the gcc compilation tool

We can use the -D option to dynamically define the macros needed by the program

For example, we can compile gcc test.c-o test-WIN32 so that the program can run under Windows (of course, in Windows environment, _WIN32 is already defined). The -D option in gcc will define the macro as 1 by default, and use the equals sign if you want to define other values such as -D _WIN32=0

Most of the time, especially on real projects, we use the cmake tool to build our own applications.

In cmake

We can write ADD_DEIFNITIONS(-D _WIN32) in CMakeLists.txt to add the macros used by the program when it runs. However, once we need to modify the macro we are using, we will have to modify the CMakeLists.txt file, which will be very troublesome.

Here's what we can do:

Written in CMakeLists.txt


IF(ENVIRO)
 ADD_DEFINITIONS(-D _WIN32)
ENDIF(ENVIRO)

In this way, we can add the -D option when using the cmake command, and define the ENVIRO command as follows

cmake-D ENVIRO=1, or cmake-D ENVIRO=ON

To cancel this definition you can use cmake-D ENVIRO=OFF or cmake-D ENVIRO=0 or cmake-U ENVIRO

That's s it. I hope it helped you. The e level is limited, there are mistakes in the place please forgive, and sincerely invite correction.


Related articles: