首先typeof这个东西并不是ISO/IEC 9899:1999里的,也就是说不是标准C的运算符,这是gcc的一个扩展。在gcc的官方文档中单独列了一章来说这个东西(5.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 Section 5.39 [Alternate Keywords], page 239.
A typeof-construct can be used anywhere a typedef name could be used. For example,
you can use it in a declaration, in a cast, or inside of sizeof or typeof.
typeof is often useful in conjunction with the statements-within-expressions feature.
Here is how the two together can be used to define a safe “maximum” macro that 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, let’s 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
which 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 will crash; 3.2.1 and later give an error).
Code which relies on it should be rewritten to use typeof:
typedef typeof(expr) T;
This will work with all versions of GCC.
这里大概叙述了typeof是一个什么东西,怎么用,实际上可以用简单的话来重述。如果你对sizeof很熟悉的话,那么大可进行类推,sizeof(exp.)返回的是exp.的数据类型大小,那么typeof(exp.)返回的就是exp.的数据类型。值得注意的是在上面的话里我们可以看到,如果编译选项中指定了使用标准C,那么gcc的扩展使用可能会受到影响,不过在gcc编译条件下使用 __typeof__依然可以正常工作,这和使用asm是一样的。当然如果是在其他的编译器条件下,这样做也不行了,只能自定义一个macro去使用,也就是说跟gcc没啥关系了,你愿意把typeof咋实现都可以。
下面写一个小程序示例一下:)
#include <stdio.h>
typedef struct
{
int x;
char y;
}astruct, * pastrcut;
int main()
{
int sizem, sizew;
int x = 3;
typeof(&x) m;
sizem = sizeof(m);
*m = 5;
typeof(((astruct *)5)->y) w;
sizew = sizeof(w);
w = ''a'';
return 1;
}
首先看main函数里的m变量,这个变量的类型就是typeof(&x),由于x是int型的(这里与x是否被赋值一点关系都没有)所以&x应该是int *类型,那么typeof(&x)返回的类型就是int*,所以m自然也就是个int*类型的。之后我们看w变量,其类型是typeof(((astruct *)0)->y),其中astruct是一个被定义的结构类型,其中的y元素是char*类型,那么((astruct *)0)->y是啥意思呢?在这里0并不是真正的变量,可以把它理解为一个替代使用的符号当然这个符号最好是一个数,其意思更可以理解为一个被赋值了的变量,这个数可以不是0,3也可以8也可以,随便什么都可以。那么((astruct *)0)->y仅仅就是表示了y这个变量,所以typeof的结果就是y元素的类型,也就是char。