We recommend that you use the following min macro definition in the GCC document:
Reference: # define min (x, y )/
(_ Extension __/
({/
Typeof (x) _ x = (x), _ y = (y );/
(_ X <__ y )? _ X :__ y ;/
})/
)
This article discusses the significance of this practice.
1. Side effects of traditional min
2. ({Statement List}) Extension in GCC
3. typeof (expression)
4. _ extension _
5. Use typeof and ({}) to implement min, avoiding side effects
Appendix 1. Solutions in the earlier version of GCC
Appendix 2. How to Use template in C ++
1. Side effects of traditional min
Min is usually defined as a macro like this:
# Define min (x, y) (x) <(y )? (X): (y ))
This definition has some side effects. For more information, see the following example:
Int x = 1, y = 2;
Int main ()
{
Printf ("min = % d/N", min (x ++, y ++ ));
Printf ("x = % d, y = % d/N", x, y );
}
After the execution of min (x ++, y ++), we expect the value of X to be 2, and the value of Y to be 3.
However, the actual result is that after the mini (x ++, y ++) is executed, the value of X is 3, and the value of Y is 3, the reason is that X ++ was executed twice after the macro scale was launched:
Reference:
Int x = 1, y = 2;
Int main ()
{
Printf ("min = % d/N", X ++ <y ++? X ++: Y ++ );
Printf ("x = % d, y = % d/N", x, y );
}
2. ({Statement List}) Extension in GCC
({Statement List}) is an expression. The comma expression is similar, but it is more powerful ({And }) it can contain multiple statements (variable definitions and complex control statements). The value of this expression is the value of the last statement in the Statement List. For example:
Int main ()
{
Int result = ({
Int I, sum = 0;
For (I = 1; I <= 100; I ++)
Sum + = I;
SUM;
})
Printf ("result = % d/N", result );
}
Running result:
Result = 5050.
3. typeof (expression)
Typeof (expression) is used to obtain the expression type. For example:
Int main ()
{
Int integer;
Typeof (100) I;/* expression 100 is of the int type and defines the int type variable I */
Typeof (integer) J;/* The expression integer is of the int type and defines the int type variable J */
I = 1;
J = 2;
}
4. _ extension _
GCC introduces many extensions not available in Standard C, such as ({And)}. GCC provides the pednatic option to check whether the program uses GCC extensions, when you use the pedantic option to compile the following program:
Int main ()
{
Int result = ({
Int I, sum = 0;
For (I = 1; I <= 100; I ++)
Sum + = I;
SUM;
})
Printf ("result = % d/N", result );
}
The compiler sends a warning:
$ CC-pedantic test. c
Test. C: In the 'main' function:
Test. C: 9: Warning: iso c does not allow curly braces in expressions.
The compiler reminds programmers that this C program uses a syntax that does not conform to the iso c standard. If other compilers (non-GCC) are used to compile this code, errors may occur. After the _ extension _ keyword is added before all expressions that use the GNU extension keyword, the compiler will not issue a warning when the pedantic option is used for compilation:
Int main ()
{
Int result = _ extension __({
Int I, sum = 0;
For (I = 1; I <= 100; I ++)
Sum + = I;
SUM;
})
Printf ("result = % d/N", result );
}
$ CC-pedantic test. c
$ Compiled successfully!
5. Use typeof and ({}) to implement min, avoiding side effects
# Define min (x, y )/
({/
Typeof (x) _ x = (x), _ y = (y );/
(_ X <__ y )? _ X :__ y ;/
})
An example of problems that may occur when using traditional min:
Int x = 1, y = 2 ;;
Int main ()
{
Printf ("min = % d/N", min (x ++, y ++ ));
Printf ("x = % d, y = % d/N", x, y );
}
It is extended
Reference:
Int x = 1, y = 2 ;;
Int main ()
{
Printf ("min = % d/N ",({
Typeof (x) _ x = (x ++), _ y = (Y ++);/* defines two integer variables */
(_ X <__ y )? _ X :__ y;
})
);
Printf ("x = % d, y = % d/N", x, y );
}
During the execution of min (x ++, y ++), X ++ and Y ++ only run once, so the result is correct.
Appendix 1. Solutions in the earlier version of GCC
The earlier version of GCC provides two built-in operators :?, ? Returns a larger value of the two operands. The min defined by the two operators is as follows:
# Define min (x, y) (x) # define max (x, y) (x)>? (Y ))
However, the new GCC document states that these two operators are outdated and we recommend that you do not use them.
Appendix 2. How to Use template in C ++
Template
Type min (type A, type B)
{
Return a <B? A: B;
}
Source: http://www.chinaunix.net/jh/23/934870.html
Add Linux kernel min, Max define:
Include/Linux/kernel. h
/*
* Min ()/MAX () macros that also do
* Strict type-checking .. see
* "Unnecessary" pointer comparison.
*/
# Define min (x, y )({/
Typeof (x) _ x = (x );/
Typeof (y) _ y = (y );/
(Void) (& _ x = & _ y );/
_ X <_ y? _ X: _ y ;})
# Define max (x, y )({/
Typeof (x) _ x = (x );/
Typeof (y) _ y = (y );/
(Void) (& _ x = & _ y );/
_ X> _ y? _ X: _ y ;})
Min and Max macros:
/*
* Min ()/MAX () macros that also do
* Strict type-checking .. see
* "Unnecessary" pointer comparison.
*/
# Define min (x, y) ({typeof (x) _ x = (x); typeof (y) _ y = (y); (void) (& _ x = & _ y); _ x <_ y? _ X: _ y ;})
# Define max (x, y) ({typeof (x) _ x = (x); typeof (y) _ y = (y); (void) (& _ x = & _ y); _ x> _ y? _ X: _ y ;})
/*
*. And if you can't take the strict
* Types, you can specify one yourself.
*
* Or not use min/max at all, of course.
*/
# Define min_t (type, x, y) ({type _ x = (x); Type _ y = (y); _ x <_ y? _ X: _ y ;})
# Define max_t (type, x, y) ({type _ x = (x); Type _ y = (y); _ x> _ y? _ X: _ y ;})
It doesn't feel a little different from what we use:
(Void) (& _ x = & _ y );
(Void) (& _ x = & _ y) The statement itself is a nonsense in terms of program execution. Its role is, in itself, we cannot perform this operation typeof (_ x) = typeof (_ y). Therefore, it is obviously impossible to determine whether the two address pointers are equal, however, if the _ x and _ y types are different, the pointer types will be different. If two different pointer types are compared, a compilation warning will be thrown. That is to say char * P; int * q; then p = Q;, this judgment will generate a warning during compilation because one is char * and the other is int. Clever here.
Because the kernel is developed together by many developers, there are some other implementations, just like what we usually use:
# Define min (A, B) (a) <(B ))? (A): (B ))
Imagine:
Min (++ A, ++ B) ==> (++ A) <(++ B ))? (++ A) :( ++ B)
Is there a problem? The input parameter is added twice.