Next: Conditionals, Previous: Constructing Calls, Up: C Extensions

### 6.6 Referring to a Type with `typeof`

Another way to refer to the type of an expression is with `typeof`. The syntax of using of this keyword looks like `sizeof`, but the construct acts semantically like a type name defined with `typedef`.

There are two ways of writing the argument to `typeof`: with an expression or with a type. Here is an example with an expression:

         typeof (x[0](1))

This assumes that `x` is an array of pointers to functions; the type described is that of the values of the functions.

Here is an example with a typename as the argument:

         typeof (int *)

Here the type described is that of pointers to `int`.

If you are writing a header file that must work when included in ISO C programs, write `__typeof__` instead of `typeof`. See Alternate Keywords.

A `typeof` construct can be used anywhere a typedef name can be used. For example, you can use it in a declaration, in a cast, or inside of `sizeof` or `typeof`.

The operand of `typeof` is evaluated for its side effects if and only if it is an expression of variably modified type or the name of such a type.

`typeof` is often useful in conjunction with statement expressions (see Statement Exprs). Here is how the two together can be used to define a safe “maximum” macro which operates on any arithmetic type and evaluates each of its arguments exactly once:

         #define max(a,b) \
           ({ typeof (a) _a = (a); \
               typeof (b) _b = (b); \
             _a > _b ? _a : _b; })

The reason for using names that start with underscores for the local variables is to avoid conflicts with variable names that occur within the expressions that are substituted for `a` and `b`. Eventually we hope to design a new form of declaration syntax that allows you to declare variables whose scopes start only after their initializers; this will be a more reliable way to prevent such conflicts.

Some more examples of the use of `typeof`:

- This declares `y` with the type of what `x` points to.

                typeof (*x) y;

- This declares `y` as an array of such values.

                typeof (*x) y[4];

- This declares `y` as an array of pointers to characters:

                typeof (typeof (char *)[4]) y;

  It is equivalent to the following traditional C declaration:

                char *y[4];

  To see the meaning of the declaration using `typeof`, and why it might be a useful way to write, rewrite it with these macros:

                #define pointer(T)  typeof(T *)
                #define array(T, N) typeof(T [N])

  Now the declaration can be rewritten this way:

                array (pointer (char), 4) y;

  Thus, `array (pointer (char), 4)` is the type of arrays of 4 pointers to `char`.

Compatibility Note: In addition to `typeof`, GCC 2 supported a more limited extension that permitted one to write

         typedef T = expr;

with the effect of declaring T to have the type of the expression expr. This extension does not work with GCC 3 (versions between 3.0 and 3.2 crash; 3.2.1 and later give an error). Code that relies on it should be rewritten to use `typeof`:

         typedef typeof(expr) T;

This works with all versions of GCC.