typeof关键字是C语言中的一个新扩展。只要可以接受typedef名称,Sun Studio C 编译器就可以接受带有typeof的结构,包括以下语法类别:
编译器接受带双下划线的关键字:__typeof和__typeof__。本文中的例子并没有遵循使用双下划线的惯例。从语句构成上看,typeof关键字后带圆括号,其中包含类型或表达式的名称。这类似于sizeof关键字接受的操作数(与sizeof不同的是,位字段允许作为typeof实参,并被解释为相应的整数类型)。从语义上看,typeof 关键字将用做类型名(typedef名称)并指定类型。
下面是两个等效声明,用于声明int类型的变量a。
typeof(int) a; /* Specifies variable a which is of the type int */
typeof('b') a; /* The same. typeof argument is an expression consisting of
character constant which has the type int */
以下示例用于声明指针和数组。为了进行对比,还给出了不带typeof的等效声明。
typeof(int *) p1, p2; /* Declares two int pointers p1, p2 */
int *p1, *p2;
typeof(int) * p3, p4;/* Declares int pointer p3 and int p4 */
int * p3, p4;
typeof(int [10]) a1, a2;/* Declares two arrays of integers */
int a1[10], a2[10];
如果将typeof用于表达式,则该表达式不会执行。只会得到该表达式的类型。以下示例声明了int类型的var变量,因为表达式foo()是int类型的。由于表达式不会被执行,所以不会调用foo函数。
extern int foo();
typeof(foo()) var;
请注意,typeof构造中的类型名不能包含存储类说明符,如extern或static。不过允许包含类型限定符,如const或volatile。例如,下列代码是无效的,因为它在typeof构造中声明了extern:
typeof(extern int) a;
下列代码使用外部链接来声明标识符b是有效的,表示一个int类型的对象。下一个声明也是有效的,它声明了一个使用const限定符的char类型指针,表示指针p不能被修改。
extern typeof(int) b;
typeof(char * const) p = "a";
typeof构造的主要应用是用在宏定义中。可以使用typeof关键字来引用宏参数的类型。因此,在没有将类型名明确指定为宏实参的情况下,构造带有所需类型的对象是可能的。
另外一篇:
另一种引用一个表达式类型的方法就是使用typeof,使用这个关键字的语法看上去有点像使用sizeof,但从本质上讲,它更像是使用typedef定义一个类型名称。
可以使用表达式或是一个类型名来引用类型。比如下面是一个使用表达式的例子:
typeof (x[0](1))
这里假设x是一个指向多个函数的指针数组。这里得到的类型实际是函数值的类型。
下面是一个使用类型名的例子:
typeof (int *)
这里得到的类型是指向int型的指针
如果你要把typeof写在头文件中,而且这些头文件是要用在ISO C程序中,那么应该写成__typeof__而不是typeof
typeof能被用在任何需要引用类型名的情况下,比如你可以用在声明、显示类型转换(cast)或是在sizeof和typeof内使用。
typeof在协助内嵌表达式的声明时非常有用。这里演示一个如何定义一个安全(在任何情况下,各参数只会被计算一次)的求最大值的宏。
#define max(a,b)
({
typeof (a) _a = (a);
typeof (b) _b = (b);
_a > _b ? _a : _b;
})
让局部变量名以下划线开关的原因是避免与内嵌表达式被使用时传进来的参数名相冲突。我们更希望建立一种新的语法规则,按照这种语法规则,声明的变量的作用域只在该变量初始化之后。相信这会是一种更加可靠的避免冲突的方法。
一些别的使用typeof的例子:
1、y的类型与x所指向的类型相同
typeof (*x) y;
2、 y的类型是指向字符的指针数组
typeof ( typeof (char *) [4]) y;
这与传统C的方法char *y[4];作用相同
来看看使用typeof声明的意义以及为什么说它很用:
#define pointer(T) typeof (T *)
#define array(T, N) typeof(T [N])
于是声明就可以写成以下形式:
array (pointer (char), 4) y;
因此y的类型就是有四个元素、这些元素指向char类型的指针数组。
关于兼容性:在GCC 2中提供了一个更加局限的扩展,这个扩展允许用户使用typedef T = expr;以使T类型与expr类型相同。这个扩展在GCC3.0和3.2版本中会出现问题,在3.2.1及以后的版本中会报错。不过可以用下面的方法来重写:
typedef typeof(expr) T;
这种方法写的代码在所有GCC版本中都可行。
原文: http://gcc.gnu.org/onlinedocs/gcc-4.3.3/gcc/Typeof.html#Typeof
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 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
:
y
with the type of what x
points to.typeof (*x) y;
y
as an array of such values.typeof (*x) y[4];
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 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.