The use of preprocessor in C language programming _c language

Source: Internet
Author: User
Tags mixed

Preprocessing the biggest sign is uppercase, although this is not a standard, but please capitalize in the use, for their own, but also for posterity.

Preprocessor in general, the most commonly used or macro, here is a summary of the use of preprocessor.

    • #include <stdio.h>
    • #define Macro_of_mine
    • #ifdef Macro_of_mine
    • #else
    • #endif

The above five preprocessing is most commonly seen, the first one represents the inclusion of a header file, you can understand that without it many functions are not available, such as C language does not put input into the standard, but the use of library functions to provide, So we can use those input and output functions only if we include the stdio.h header file. #define则是使用频率第二高的预处理机制, the definition of a constant is widely used, except that it differs from the constants declared by the const:

#define MAR_VA
const int con_va = m;
...
/* Define two arrays */
...
for (int i = 0;i < 10;++i)
{
  mar_arr[i] = Mar_va;
  Con_arr[i] = Con_va;
}

Difference 1, the definition of Mar_va can be used for array dimensions, and Con_va is not
Difference 2, in use, the principle of mar_va is found in the text of all the use of its own place, with value substitution, that is to say Con_va will only have an authentic, and Mar_va will have n authentic (n for the number of uses) the remaining three is in the protection of the first file is used a lot.
A few of the more practical for debugging macros, from the C language with

    • __LINE__ and __file__ are used to display the current line number and the current file name
    • __DATE__ and __time__ are used to display the current date and time
    • __FUNC__ (C99) is used to display the name of the current outer function

The five kinds of macros mentioned above are used directly as values.

__stdc__

If you want to verify that the compiler you are using now is following the ISO standard, use it if it is his value of 1.

printf ("%d\n", __stdc__);

Output: 1

If you want to further determine whether the standard version used by the compiler is C99 or C89 you can use __stdc__version__,c99 (199901)

printf ("%d\n", __stdc_version__);

Output: 199901

For #define

The preprocessor is generally valid only for the same row, but it can be read continuously if the backslash is added

 #define ERR (flag) \
   if (flag) \
    printf ("correctly")

Can be seen, and not added at the end; not because the macros don't need to, but because we always use the macro approximation as a function, and the function call always ends with, in order not to cause confusion, we do not add it by default in the macro definition, but in the code source file to prevent the definition of confusion.

Pretreatment can also bring some convenience

  #define SWAP1 (A, b) (A = b, b = a-b, A-= b)
  #define SWAP2 (x, y) {x ^= y; y ^= x; x ^= y}

The previous example, the exchange of two-digit macro writing can effectively avoid the function overhead, because it is directly at the call to expand the code block, so it is more directly embedded code. However, occasionally there will be some disharmony errors, for beginners:

 int v1 = ten;
 int v2 =;
 SWAP1 (v1, v2);
 SWAP2 (v1, v2)/error

For the above code block case, why SWAP2 error? For the average beginner, often ignore such as, Goto do...while and other rare keyword usage, so rarely see SWAP1 writing, mostly focused on the SWAP2 of similar errors, wrong on the wrong in {} represents a block of code, do not need to use; To end, this is the most error-prone place for macros A macro simply expands the code without any processing. For this, even the veteran also often stumble, there is a single chip computer and other places in the C language can be used for reference to protect code:

 #define SWAP3 (x, y) do{\
     x ^= y; y ^= x ^= y; \
     }while (0)

This allows you to safely use the code in curly braces in your code, and, as previously agreed, makes the use of a macro look like a function.

But the so-called, false is always false, even if the macro how like a function, it is still not a function, if you really think of it as a function, you will at some time wrong touch the mind, or a classic example, compare size:

 #define CMP (x, y) (x > Y x:y)
 ...
 int x = m, y =;
 int result = CMP (x, y++);
 printf ("x =%d, y =%d, result =%d\n", x, y, result);

What will the output be if you execute this part of the code? The answer is, I don't know! At least the value of result we can't be sure, we'll expand the code to get

 int result = (x > y++ x:y++);

It looks as if Y is incremented two times, and the final result must be 200. Is that so? C language standard for a certain program statement, an object can only be modified once, and more than once the result is undetermined, and the compiler decides that, in addition to the three-mesh operator, there are && Or, in, or function parameter call, switch control expression, for the control statement from this can be seen, the use of macros is also risky, so although the macro is strong, but still can not be abused.

For a macro, as you've said before, it's simply unfolding, which sometimes poses some problems:

 #define MULTI (x, y) (x * y)
 ...
 int x = m, y =;
 int result = MULTI (x+y, y);

Do you see the problem? Expands to become: int result = X+y * y; Completely contrary to what we thought at the time of our design, a better way to modify it is to put parentheses around each parameter: #define MULTI (x, y) ((x) * (y)) so that after the expansion:

 int result = ((x+y) * (y));

This will solve some of the problems to a large extent.

If you are very confident in your own macros, you can nest macros, that is, you use macros as parameters in one expression, but macros only expand this level of macros, for multilevel macros there is another way to expand

 int result = MULTI (MULTI (x, y), y);

Expand into:

int result = (((((x) * (y))) (y));

The application of macros

Since we do not understand whether a macro has been defined in some cases (the null macro is an exception and it can be defined repeatedly), we can use some preprocessing protection mechanisms to prevent errors from occurring

    • #ifndef My_macro
    • #define MY_MACRO 10000
    • #endif

If My_macro is defined, then the following statement is not executed, and if not defined then executed.

There are two useful operators in the use of macros, let's call it operator #, # #

For # We can assume that the function of the # operator is to convert the macro parameter to a string.

  #define HCMP (x, y) printf (#x "is equal to" #y "?%d\n", (x) = = (y))
  ...
  int x = m, y =;
  HCMP (x, y);

After unfolding

  printf ("x is equal to Y?") %d\n ", (100) = = (200));

Note: You can add the compiler option yourself to see the code after the macro expands, and you can query the expansion options for GCC, no longer detailed here. Especially in the nested use of multilayer macros, but I do not recommend, so do not do much introduction.

Can say is how to correctly handle some nested use, the reason is not willing to say more than to use, because the C preprocessor is a wonderful
Give a typical example of the use of __line__ and __file__.

  /* Below will be said to the # preprocessing indicator, here first, really do not understand, you can try it yourself * *
  #define WHERE_AM_I #__LINE__ "lines in" __file__
  ...
  Fputs (Where_am_i, stderr);

Is this going to work? If I can tell you what to do.

  /* Common sense this should be able to work, but the compiler does not say this error///
  ///* Fortunately, some predecessors have trod the pit, leaving us a solution * * *
  #define DEPAKEGE (x) #X
  #define PAKEGE (x) depakege (X)
  #define Where_am_i Pakege (__line__) "lines in" __file__
  ...
  Fputs (Where_am_i, stderr);

Don't ask me why, because I don't know what the real working mechanism of C preprocessor is.

The first time I saw this solution was in Windows core programming, and this book still gives me a lot of help, though it's fading out of the bookshelf

Summing up, the macro parameters are automatically converted to string constants by the preprocessor after they are placed in the # operator, and escaping is done automatically by the preprocessor without the need for us to add escape symbols.

For # #
it does this by merging the parameters on both sides of the operator into a complete tag, but it is important to note that since the preprocessor is only responsible for unfolding, the programmer has to make sure that the token is legitimate, and there are some writing issues that are listed

   #define Merge (x, y) Have_define_ # # (x + y)
   #define Merge (x, y) have_define_##
   result = MERGE (1, 3);

Here, first of all, I use the second type because of the customary reason, but no matter which is harmless, the effect is the same. What happens after the code is expanded?

result = Have_define_1 + 3;

In my opinion, this is a bit of C + + in the template idea, although very primitive, but there is always a direction, by virtue of this method we can use the macro to do similar but different functions of the call, although we can use the function pointer array to store, but need to know in advance there are several functions And if you want to achieve dynamic growth, you need to consume memory allocations, but macros are different.

   inline int func_0 (int arg_1, int arg_2) {return arg_1 + arg_2;}
   inline int func_1 (int arg_1, int arg_2) {return arg_1-arg_2;}
   inline int func_2 (int arg_1, int arg_2) {return arg_1 * arg_2;}
   inline int func_3 (int arg_1, int arg_2) {return arg_1/arg_2;}
   #define Call (x, Arg1, arg2) func_# #x (arg1, arg2) ...
     printf ("func_%d return%d\n", 0, call (0, 2,));
     printf ("func_%d return%d\n", 1, call (1, 2,));
     printf ("func_%d return%d\n", 2, Call (2, 2,));
     printf ("func_%d return%d\n", 3, Call (3, 2, 10));

A very simple usage, when we increase the reduction of functions we do not have to consider how to find these functions only need to write down the corresponding number of each function, but still that sentence, can not be abused.

   #define CAT (temp, i) (cat# #i)
   //...
   for (int i = 0;i < 5;++i)
   {
     int CAT (x,i) = I*i;
     printf ("x%d =%d \ n", I,cat (X,i));
   }

For macro, it is important to note that macros can only expand the current layer of macros, if you nest using macros, the macro as a macro parameter, it will cause the macro can not fully expand, that is, as a parameter of the macro can only pass the name to the external macro

  #define WHERE (Value_name, line) #value_name #line
  ...
  Puts (WHERE (x, __line__)); x = 11

Output: 11__line__

For other precompiled directives, such as: #program, #line, #error和各类条件编译并不在此涉及, because there are no traps or difficulties in using them.

C and C + + mixed programming scenarios

Often in the source code to see the extern "C" such a figure, this is what to do?
This is designed for mixed programming, often appearing in the source code of C + + to enable C + + to successfully invoke standard or non-standard functions of C.

  #if defined (__cplusplus) | | Defined (_cplusplus)
      extern "C" {
  #endif

      /** Body Code **/

  #if defined (__cplusplus) | | defined (_cplusplus)
      }
  #endif

This makes it possible to call C's code in C + +.

Functions that invoke C + + in C need to be aware that overload functionality cannot be used or will fail, for the reasons described in C + + for the implementation of overloaded functions. can also be called mangle

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.