OBJECTIVE-C macro Definition Detailed description _ios

Source: Internet
Author: User

Like to read some Open-source project source, always will find that the great God's code always have some short and efficient macro definition, click to see, find obscure, not to mention learning, sometimes understanding is a difficult, but the macro definition itself is not so difficult, But write a good macro of course still need rich experience and technology, then say a macro definition, see the Big God's macro is the first step, occasionally write A is also a good way to install force ~

Defined:

There are two types of macro definitions: One is an Object macro (Object-like macro) and the other is a function macro (Function-like macro)

It is also understood by name that an object macro is used to define a quantity through which a variable can be obtained, such as we define a PI value: #define PI 3.1415926 There is no need to write a floating-point number if the PI value is used here. and the direct use of pi is quite written to this constant floating-point number, the essence of the meaning of the code is to replace the PI in the compile phase of the real constants, generally used to define some commonly used constants, such as screen width, system version number. But note that when you define an expression as a macro, you need to look through the surface of the macro to see the nature of the compiler, for example

#define MARGIN 10 + 20

But when you use it to calculate a width, if you use margin * 2, the result will not be what you want, you will get a 50 instead of 60, and you can expand the expression to see

MARGIN * 2//open to get
10 + 20 * 2 = 50

We need to take into account its operation priority, the solution is very simple, and then its outer layer plus a small bracket

#define MARGIN (+)
//MARGIN * 2
//(10 + 20) * 2 = 60

function macros function like a function, it can pass parameters, through the parameters of a series of operations, such as our commonly used to calculate the maximum number of two, we can define

#define MAX (a,b) A > B? A:b

This seems to be no problem, and it's not a problem to make a simple comparison with Max (1,2), but when someone uses your macro to do more complex calculations, there's a new problem, such as a three-value calculation, that might write

int a = 3;
int b = 2;
int c = 1;
MAX (A, B > C. b:c)//
= 2

The result is certainly not what you want, the maximum is obviously 3, but the result of the calculation is 2, what happened to the calculation error, we can expand the macro to find out, the following is the expansion of the macro

MAX (A,b > C b:c);
a > B > C? B:c? A:b > C? B:C
//(A > (b > C. b:c) a:b) > C. B:C//This is the priority//band value of the operation/
/(3 > (2 > 1? 2: 1)? 3:2) > 1? 2:1
//(3 > 2 3:2) > 1? 2:1
//3 > 1? 2:1

Everyone must have seen the problem, or because of priority issues, so remember that, anyway, write two parentheses will not be tired, regardless of whether there will be problems, write the parentheses are insured some ~
However, there are always writing a wonderful way to write will appear, and to look up also very reasonable appearance ~

c = MAX (a++,b); * * I'll just start to show you * * */
c = a++ > B a++: B
//c = 3++ > 2? 3++: 2
//c = 4
//a = 5

No matter how bad the person is, it seems like there's no problem, all we have to deal with, but using our normal parentheses is out of the question, we need to use the assignment extension ({...}) Believe that a friend has recognized this usage, we can use this method to calculate an object, without wasting variable names, can form a small scope of scopes to compute special values

int a = ({
 int b = ten;
 int c =;
 B + C;
})
A =;
int b; Continue to use B and C when the variable name is also no problem
int C;

How can we modify this macro to adapt to this pit dad's writing?

#define MAX (A,b) ({__typeof (a) __a = (a); __typeof (b) __b = (b); __a > __b? __a: __b;})

__typeof () is a variable value that is converted to the same type. The perfect solution to this problem, but there is a not how to happen in the accident, through the above also can know, we generated a new variable __a, __b, how someone used __a,__b, you should repeat for variable name and compile error, If someone uses this, you can pick up your keyboard and hit him in the face, cause of course not __a make your macro wrong, but __a what it means, the importance of variable name is self-evident, unless you and the people who look at the code, otherwise please use a meaningful variable name, So let's take a look at how the official Max was implemented.

#define __NSX_PASTE__ (a,b) a# #B

#if!defined (MAX)
  #define __NSMAX_IMPL__ (a,b,l) ({__typeof__ (A) __nsx_paste_ _ (__a,l) = (a); __typeof__ (b) __nsx_paste__ (__b,l) = (b); (__nsx_paste__ (__a,l) < __nsx_paste__ (__b,l))? __NSX_PASTE__ (__b,l): __nsx_paste__ (__a,l); )
  #define MAX (a,b) __nsmax_impl__ (a,b,__counter__)
#endif

This is the max definition in the function framework, and I'm going to parse it step-by-step, and the first thing I see is

#define __NSX_PASTE__ (a,b) a# #B
Connect A and B to a piece

Its function is to connect A and B to a piece, to generate a string, such as a# #12就成了A12

Next we see a macro definition __nsmax_impl__ (a,b,__counter__) with three parameters.

#if!defined (MAX)
  #define __NSMAX_IMPL__ (a,b,l) ({__typeof__ (a) __nsx_paste__ (__a,l) = (a); __typeof__ (B) __nsx_ paste__ (__b,l) = (b); (__nsx_paste__ (__a,l) < __nsx_paste__ (__b,l))? __NSX_PASTE__ (__b,l): __nsx_paste__ (__a,l); )
  #define MAX (a,b) __nsmax_impl__ (a,b,__counter__)
#endif

Let's first explain what __counter__ is, __counter__ is a precompiled macro that will add 1 to each compile, so that the variable names generated by __nsx_paste__ (__b,__connter__) are not easily duplicated. But this is still a little dangerous, that is, if you get the variable name __a20, it really really has no way ~

Variable parameter macros

Speaking of variable parameters, we use the most of a method NSLog (...) is the variable parameter, the variable parameter means that the number of parameters is indefinite, and nslog as we debug when an important tool is too waste, can only print the corresponding time and parameter information, and the file name, line number, method name and other important information are not given, Today we will use this to realize a super version NSLog macro ~ ~ ~

#define NSLOG (format, ...) do {fprintf (stderr, "<%s:%d>%s\n", \ [[
nsstring stringwithutf8string:__file__] L Astpathcomponent] utf8string], __line__, __func__); \
(NSLOG) (format), # #__VA_ARGS__); \
fprintf (stderr, "-------\ n"); \} while (0)

First look at the definition of the macro nslog (format,...) found that it has ..., this is the variable parameter, and __va__args__ is except the format all the rest of the parameters, then we found that the use of a do{}while (0) loop, that the loop is only executed one time to stop, feel nonsense ah, our goal is only to execute again AH , but it's written for defensive programming, if anyone writes that.

if (> 99)
NSLog (@ "%@", @ "fuck");

will appear anyway will be executed after two print, the problem must everyone also know, then we directly use {} to expand the line, the actual operation is really solved this problem, but again, when we use the if{} else if{} when there will be new problems

if (>)
 NSLog (@ "%@", @ "fuck");
else {
}
//Expanded available
if (>)
{fprintf (stderr, <%s:%d>%s\n),
 [[[NSString Stringwithut F8STRING:__FILE__] lastpathcomponent] utf8string], __line__, __func__);
 (NSLOG) (format), # #__VA_ARGS__);
 fprintf (stderr, "-------\ n");
else {
}

Compile error, we also found that the NSLog will follow, if I do not use {}, will be added to the outside at compile time, resulting in compilation errors, and the use of do{} while (0) loop does not occur after the problem

if (>) do
 {fprintf (stderr, "<%s:%d>%s\n", [[[
 nsstring stringwithutf8string:__file__] Lastpa Thcomponent] utf8string], __line__, __func__);
 (NSLOG) (format), # #__VA_ARGS__);
 fprintf (stderr, "-------\ n");} while (0);
else {
}

To this location problem solved almost, look at the internal structure, __file__ is the file path compiled, __line__ is the number of lines, __func__ is the compiled method name, the following we saw

(NSLOG) (format), # #__VA_ARGS__);

# #上面已经看见过了, the role here is similar to the meaning of the connection, __va_args__ is the rest of the parameters, using the # #连接起来后就时NSLog (format,__va_args__), this is the NSLog method, But do not know if anyone found a detail, if the __va_args__ is empty, it is not a nslog (format,) this will certainly compile the error, but Apple's great God had thought of the solution, if __va_args__ for empty words, here # # Will swallow the front, and this will not be a problem. Then we can use this powerful NSLog ().

Then let's talk about the use of multiple parameter functions

-(void) say: (NSString *) code,... {  
  va_list args;
  Va_start (args, code);
  NSLog (@ "%@", code);
  while (YES) {
    NSString *string = Va_arg (args, NSString *);
    if (!string) {break
      ;
    }
    NSLog (@ "%@", string);
  }
  Va_end (args);
}

We can define a va_list args to define a multi-parameter variable args, and then start the value by Va_start (args, code), which is the first value, Va_arg (args, NSString *) to define the type of value taken out. The value method is a bit like a generator, which is then called Va_end (args) to close. This is the whole process, usually rarely use this method, if you have any good practical methods please comment ~ ~ ~

Thank you for reading, I hope to help you, thank you for your support for this site!

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.