c++ typeof
600 Words|Read in about 3 Min|本文总阅读量次
本文以最通俗易懂的方式熟悉c++ typeof。
0简介
Typeof用于指定变量的数据类型,该关键字使用时的语法类似sizeof,但是其结构在语义上类似于用typedef定义的类型名称。 Typeof有两种形式的参数:表达式 或者 类型。
GCC的一个扩展,具体可以点击这里
下面是使用表达式作为参数的例子:
1typeof(x[0](1))
在此假设x是一个函数指针数组;该类型描述的是函数返回值。
下面是使用类型作为参数的例子:
1typeof(int *)
在此该类型描述的是一个指向int的指针。
如果在一个被包含在ISO C程序中的头文件中使用该关键字,请使用__typeof__代替typeof。 typeof可用在任何可使用typedef的地方,例如,可将它用在声明,sizeof或typeof内。
typeof在声明中与表达式结合非常有用,下面是二者结合用来定义一个获取最大值的“宏“:
1#define max(a,b) \ 2 ({ typeof (a) _a = (a); \ 3 typeof (b) _b = (b); \ 4 _a > _b ? _a : _b; })
本地变量使用下划线命名是为了避免与表达式中的变量名a和b冲突。
下面是一些typeof使用示例:
声明y为x指向的数据类型
1typeof(*x) y;
声明y为x指向的数据类型的数组
1typeof(*x) y[4];
声明y为字符指针数组
1typeof(typeof(char *)[4]) y;
上述声明等价于
char *y[4];
Typeof在linux内中使用广泛,比如,宏container_of用于获取包含member的结构体type的地址:
1/** 2 * container_of - cast a member of a structure out to the containing structure 3 * 4 * @ptr: the pointer to the member. 5 * @type: the type of the container struct this is embedded in. 6 * @member: the name of the member within the struct. 7 * 8 */ 9#define container_of(ptr, type, member) ({ \ 10 const typeof( ((type *)0)->member ) *__mptr = (ptr); \ 11 (type *)( (char *)__mptr - offsetof(type,member) );})
1demo
1.1demo1
1// demo1
2int var = 2023;
3//实际上为int* pvar = &var;
4typeof(int *) pvar = &var;
5printf("pvar:\t%p\n", pvar);
6printf("&var:\t%p\n", &var);
7printf("var:\t%d\n", var);
8printf("*pvar:\t%d\n", *pvar);
我们先定义了一个 int 型变量 var,然后再定义一个指针型变量指向 var,一般我们就直接 int *xxx = &xx,但是我们为了演示 typeof 的用法,就不要这么直接了,typeof 是自动推导后面 ( ) 里的数据类型,所以 typeof(int *) 直接推导出了 int * 型,用这个类型声明了 pvar 并将其初始化为 var 的地址
1.2demo2
1// demo2
2int *pvar = NULL;
3//这里的typeof(pvar)相当于int*
4typeof(*pvar) var = 2023;
5printf("var:\t%d\n", var);
这个例子是先定义了一个整型指针变量 pvar,typeof 后面括号里的表达式为*pvar,pvar 的类型为 int * 型,那 *pvar 当然就被解析为 int 型,所以用这个类型声明的变量 var 也是 int 型
1.3demo3
1// demo3
2int *pvar = NULL;
3//根据demo2直到这里typeof(*pvar)其实就是int
4typeof(*pvar) var[4] = {2023, 02, 11, 1508};
5for (int i = 0; i < 4; i++)
6 printf("var[%d]:\t%d\n", i, var[i]);
这次 typeof 解析出来的类型跟上一个一样,区别是 var 是一个包含四个元素的数组,相当于 int var[4] = {…}
1.4demo4
1// demo4
2//内层的tyeopf是typeof(const char *) a;
3//叠加外层的typeof是typeof(a[4])类型,实际上是指针数组
4typeof(typeof(const char *)[4]) pchar = {"hello", "world", "i am", "yangyang48"};
5for (int i = 0; i < 4; i++)
6 printf("pchar[%d]:\t%s\n", i, pchar[i]);
这次嵌套了两层 typeof,我们一层一层的往外剥,先看最里层,typeof 先解析出一个 const char * 类型,有经验的 C 程序员应该马上就能联想到字符串了吧,而后面又跟着一个 [4],说明这是一个包含四个字符串的数组类型,那么这个类型也就被最外层的 typeof 给解析到了,那么最终的 pchar 也就是这个类型了,相当于 const char *pchar[4] = {…};
1.5demo5
1// demo5
2int add(int param1, int param2) {
3 return param1 + param2;
4}
5
6int sub(int param1, int param2) {
7 return param1 - param2;
8}
9
10int mul(int param1, int param2) {
11 return param1 * param2;
12}
13
14int main() {
15 //(int (*fun)(int, int)为函数指针),这里就是函数指针数组
16 int (*func[3]) (int, int) = {add, sub, mul};
17 //被typeof包起来的函数指针,函数并不会被调用
18 typeof(func[0](1, 1)) sum = 100;
19 typeof(func[1](1, 1)) dif = 101;
20 typeof(func[2](1, 1)) pro = 102;
21 printf("sum:\t%d\n", sum);
22 printf("dif:\t%d\n", dif);
23 printf("pro:\t%d\n", pro);
24
25 printf("start calc\n", pro);
26 //函数真正被调用
27 int sum1 = func[0](2023, 2);
28 int dif1 = func[1](2023, 2);
29 int pro1 = func[2](2023, 2);
30 printf("sum1:\t%d\n", sum1);
31 printf("dif1:\t%d\n", dif1);
32 printf("pro1:\t%d\n", pro1);
33 return 0;
34}
这个 demo 中先定义了三个函数,这三个函数都是返回值为 int 类型,并且接受两个 int 型的参数,然后在 main 函数中定义了一个函数指针数组 func,并用上面三个函数名将其初始化,然后我们来看底下的第一个 typeof 会推导出什么类型,func[0] 就是指 add 这个函数,后面的括号里跟了两个参数,说白了就是简单的 add(1, 1) 的调用,而 add 会返回一个 int 型值,所以最终推导出的类型就是 int 型,其它两个都是同理,所以 sum、dif、pro 其实就是三个整型数,相当于 int sum = 100; int dif = 101; int pro = 102;
说明了函数指针被typeof关键字包起来,并不会运行函数本身。
1.6demo6
1// demo 06
2#define pointer(T) typeof(T *)
3#define array(T, N) typeof(T[N])
4
5int main() {
6 //这里有点c++类模板的感觉pointer(char)实际上是typeof(char*)
7 //外面的array(typeof(char*),4)实际上是typeof(typeof(char*)[4]),跟上述demo4一致
8 array(pointer(char), 4) pchar = {"hello", "world", "i am", "yangyang48"};
9 for (int i = 0; i < 4; i++)
10 printf("pchar[%d]:\t%s\n", i, pchar[i]);
11 return 0;
12}
这里用到了宏函数,pointer(T) 会被替换为 typeof(T *),也就是说 pointer 后面跟某个类型的名字,经过预处理之后就会变成用 typeof 解析相应类型的指针类型,而 array 后面跟一个类型名和一个整数,然后 typeof 就会解析为该类型的一个数组,这样 main 函数中的 array(pointer(char), 4),pointer(char) 首先会被解析为 char * 型,然后外层的 array 会再被解析为包含 4 个 char * 元素的数组类型,所以就相当于 char *pchar[4] = {…};
2总结
typeof关键字是C语言中的一个新扩展,这个特性在linux内核中应用非常广泛。
由于typeof()
是在编译时处理的,故其中的表达式在运行时是不会被执行的,比如typeof(fun())
,fun()
函数是不会被执行的,typeof
只是在编译时分析得到了fun()
的返回值而已。
另外typeof
还有一些局限性,其中的变量是不能包含存储类说明符的,如static
、extern
这类都是不行的。