IOS development advanced: Use macros to define macros (#,##,..., _ Va_args _)

Source: Internet
Author: User

Macro definition #define has always defined some simple constants, at most it is a function, and little attention is paid to the use of macro definitions. Until I see this code:


#define PLAYSOUNDEFFECT (...) \
[[GameManager sharedGameManager] playSoundEffect: @ # __ VA_ARGS__]


Such a powerful usage has never been thought of before. Looking at some header files of the iOS Framework, it is found that almost all are macro definitions:



Have to say that the macro definition is very powerful! The use of macro definitions makes the preparation of programs easier!

As an iOS developer, it is necessary to delve into the usage of macro definitions.



The most official URL for macro instructions is: http://gcc.gnu.org/onlinedocs/cpp/Macros.html#Macros

The GNU C 4.2 Preprocessor User Guide can be found on Apple's official website, and found to be exactly the same as the instructions on the GNU official website. Because the Xcode compiler is based on the GNU C 4.2 preprocessor, the use of macros in the Objective-C development environment is exactly the same as in C / C ++.



The following text is a summary and translation after reading the official instructions. (The code is directly extracted from the official instructions)



1. Macros

Official explanation:

A macro is a fragment of code which has been given a name. Whenever the name is used, it is replaced by the contents
of the macro. There are two kinds of macros. They differ mostly in what they look like when they are used. Object-like macros resemble data objects when used, function-like macros
resemble function calls.

There are two types of macros, one is a class-like macro that encapsulates the data object used, and the other is a class-like macro that encapsulates the function call. In ObjC, it is possible to encapsulate the use of Method, such as the code at the beginning of the article



1.1 Macros of class objects

The most basic use:


#define BUFFER_SIZE 1024

foo = (char *) malloc (BUFFER_SIZE);

foo = (char *) malloc (1024);
Is the most basic replacement.

Generally, the names of macros are in capital letters.


-------------------------------------------------- ----------------------------------------------


     #define NUMBERS 1, \
                     2, \
                     3
     int x [] = {NUMBERS};
          ==> int x [] = {1, 2, 3};
In the macro definition, if you want to wrap, use the "\" symbol. Then it is still in the same line after preprocessing.

-------------------------------------------------- ----------------------------------------------

The C preprocessor reads the program in order, so the macro definition takes effect after the macro definition.

     foo = X;
     #define X 4
     bar = X;
produces

     foo = X;
     bar = 4;

-------------------------------------------------- ----------------------------------------------

When the macro is called, the preprocessor will continue to detect whether the content itself is also a macro definition when it replaces the content of the macro, and if so, it will continue to replace the content.


     #define TABLESIZE BUFSIZE
     #define BUFSIZE 1024
     TABLESIZE
          ==> BUFSIZE
          ==> 1024
-------------------------------------------------- ----------------------------------------------

The definition of the macro is subject to the last effective definition, so the following code TABLESIZE corresponds to 37


     #define BUFSIZE 1020
     #define TABLESIZE BUFSIZE
     #undef BUFSIZE
     #define BUFSIZE 37
-------------------------------------------------- ----------------------------------------------

If the macro definition contains a name, the preprocessor will terminate the expansion to prevent infinite nesting (infinite resursion)


1.2 Function-like macros


     #define lang_init () c_init ()
     lang_init ()
          ==> c_init ()
"()" Is added after the name of the function-like macro.


     #define lang_init () c_init ()
     lang_init ()
          ==> () c_init () ()
And "()" must immediately follow the name or it will be considered as an object-like macro.



1.3 Macro parameters

You can add parameters in the function-like macro to make it more like a real function


     #define min (X, Y) ((X) <(Y)? (X): (Y))
       x = min (a, b); ==> x = ((a) <(b)? (a): (b));
       y = min (1, 2); ==> y = ((1) <(2)? (1): (2));
       z = min (a + 28, * p); ==> z = ((a + 28) <(* p)? (a + 28): (* p));
The basic usage is similar to the definition of a function. Of course, the actual parameters in the macro are separated by commas. When preprocessing, first expand the macro, then put the parameters into the main body of the macro, and then check the complete content again.

-------------------------------------------------- ----------------------------------------------

If there is a string in the macro, even if it is the same as the parameter name, it will not be replaced. as follows:


     #define foo (x) x, "x"
     foo (bar) ==> bar, "x"
1.4 Stringization

Use the "#" preprocessing operator to convert the parameters in the macro into a string. Examples are as follows:


     #define WARN_IF (EXP) \
     do {if (EXP) \
             fprintf (stderr, "Warning:" #EXP "\ n");} \
     while (0)
     WARN_IF (x == 0);
          ==> do {if (x == 0)
                fprintf (stderr, "Warning:" "x == 0" "\ n");} while (0);
This stringification will stringify all characters in the parameter, including quotation marks. If there are many spaces in the parameter, only one space will be used after stringification.

Then there is no way to directly convert the parameter into a single character char

-------------------------------------------------- ----------------------------------------------


     #define xstr (s) str (s)
     #define str (s) #s
     #define foo 4
     str (foo)
          ==> "foo"
     xstr (foo)
          ==> xstr (4)
          ==> str (4)
          ==> "4"
The above result appears because when str (s) is used, s is stringified, so the macro is not expanded. When using xstr (s), s is used as a parameter, so the macro is first fully expanded and then put into the parameter.




1.5 Connection

Use the "##" operator to connect the tokens in the macro.


     struct command
     {
       char * name;
       void (* function) (void);
     };
     
     struct command commands [] =
     {
       {"quit", quit_command},
       {"help", help_command},
       ...
     };
     #define COMMAND (NAME) {#NAME, NAME ## _command}
     
     struct command commands [] =
     {
       COMMAND (quit),
       COMMAND (help),
       ...
     };
As above, the character corresponding to the parameter NAME is connected to _command without any other conversion. Of course, it must be noted that the connected characters must be meaningful, otherwise only errors or warnings will appear.

Then the C preprocessor will convert the comments into spaces, so it is possible to add comments in the middle of the macro. But you cannot put "##" at the end of the macro, otherwise an error will occur.

1.6 Multi-parameter macros (Variadic Macros)


     #define eprintf (...) fprintf (stderr, __VA_ARGS__)
     eprintf ("% s:% d:", input_file, lineno)
          ==> fprintf (stderr, "% s:% d:", input_file, lineno)
Use the identifier __VA_ARGS_ to indicate multiple parameters, and use (...) in the name of the macro

The following methods can also be used in C ++:


     #define eprintf (args ...) fprintf (stderr, args)
The result is the same.

-------------------------------------------------- ----------------------------------------------
Special usage of "##":


     #define eprintf (format, ...) fprintf (stderr, format, ## __ VA_ARGS__)
     eprintf ("success! \ n")
          ==> fprintf (stderr, "success! \ n");
Put "##" between "," and the parameter, then if the parameter is left blank, then "##" in front of "," will be deleted, thereby preventing compilation errors.

1.7 Cancel or redefine the macro
This can be understood by looking at the following code:


     #define FOO 4
     x = FOO; ==> x =
4;
      #undef FOO
      x = FOO; ==> x = FOO;

These definitions are effectively the same:

      #define FOUR (2 + 2)
      #define FOUR (2 + 2)
      #define FOUR (2 / * two * / + 2)
but these are not:

      #define FOUR (2 + 2)
      #define FOUR (2 + 2)
      #define FOUR (2 * 2)
      #define FOUR (score, and, seven, years, ago) (2 + 2)
For redefinition, if the defined macro is different, the compiler will give a warning and use the newly defined macro.

Through the summary description above, you can now easily see the meaning of the macro definition at the beginning of this article.


Related Article

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.