gcc: Typeof

1 
1 6.6 Referring to a Type with 'typeof'
1 =====================================
1 
1 Another way to refer to the type of an expression is with 'typeof'.  The
1 syntax of using of this keyword looks like 'sizeof', but the construct
1 acts semantically like a type name defined with 'typedef'.
1 
1  There are two ways of writing the argument to 'typeof': with an
1 expression or with a type.  Here is an example with an expression:
1 
1      typeof (x[0](1))
1 
1 This assumes that 'x' is an array of pointers to functions; the type
1 described is that of the values of the functions.
1 
1  Here is an example with a typename as the argument:
1 
1      typeof (int *)
1 
1 Here the type described is that of pointers to 'int'.
1 
1  If you are writing a header file that must work when included in ISO C
11 programs, write '__typeof__' instead of 'typeof'.  ⇒Alternate
 Keywords.
1 
1  A 'typeof' construct can be used anywhere a typedef name can be used.
1 For example, you can use it in a declaration, in a cast, or inside of
1 'sizeof' or 'typeof'.
1 
1  The operand of 'typeof' is evaluated for its side effects if and only
1 if it is an expression of variably modified type or the name of such a
1 type.
1 
1  'typeof' is often useful in conjunction with statement expressions
1 (⇒Statement Exprs).  Here is how the two together can be used to
1 define a safe "maximum" macro which operates on any arithmetic type and
1 evaluates each of its arguments exactly once:
1 
1      #define max(a,b) \
1        ({ typeof (a) _a = (a); \
1            typeof (b) _b = (b); \
1          _a > _b ? _a : _b; })
1 
1  The reason for using names that start with underscores for the local
1 variables is to avoid conflicts with variable names that occur within
1 the expressions that are substituted for 'a' and 'b'.  Eventually we
1 hope to design a new form of declaration syntax that allows you to
1 declare variables whose scopes start only after their initializers; this
1 will be a more reliable way to prevent such conflicts.
1 
1 Some more examples of the use of 'typeof':
1 
1    * This declares 'y' with the type of what 'x' points to.
1 
1           typeof (*x) y;
1 
1    * This declares 'y' as an array of such values.
1 
1           typeof (*x) y[4];
1 
1    * This declares 'y' as an array of pointers to characters:
1 
1           typeof (typeof (char *)[4]) y;
1 
1      It is equivalent to the following traditional C declaration:
1 
1           char *y[4];
1 
1      To see the meaning of the declaration using 'typeof', and why it
1      might be a useful way to write, rewrite it with these macros:
1 
1           #define pointer(T)  typeof(T *)
1           #define array(T, N) typeof(T [N])
1 
1      Now the declaration can be rewritten this way:
1 
1           array (pointer (char), 4) y;
1 
1      Thus, 'array (pointer (char), 4)' is the type of arrays of 4
1      pointers to 'char'.
1 
1  In GNU C, but not GNU C++, you may also declare the type of a variable
1 as '__auto_type'.  In that case, the declaration must declare only one
1 variable, whose declarator must just be an identifier, the declaration
1 must be initialized, and the type of the variable is determined by the
1 initializer; the name of the variable is not in scope until after the
1 initializer.  (In C++, you should use C++11 'auto' for this purpose.)
1 Using '__auto_type', the "maximum" macro above could be written as:
1 
1      #define max(a,b) \
1        ({ __auto_type _a = (a); \
1            __auto_type _b = (b); \
1          _a > _b ? _a : _b; })
1 
1  Using '__auto_type' instead of 'typeof' has two advantages:
1 
1    * Each argument to the macro appears only once in the expansion of
1      the macro.  This prevents the size of the macro expansion growing
1      exponentially when calls to such macros are nested inside arguments
1      of such macros.
1 
1    * If the argument to the macro has variably modified type, it is
1      evaluated only once when using '__auto_type', but twice if 'typeof'
1      is used.
1