目录
1. 从复杂类型理解类型重命名的必要性
1.1 示例1
( * (void (*) () ) 0 )();
(1)void (*) ( ) 表示函数指针类型;
注:可通过增加变量名识别:void (*p) ( )表示名为p的函数指针变量;
(2) (void (*) () ) 0 实现将0由原本的整型强制类型转换为函数指针类型;
(3)( * (void (*) () ) 0 ) ( ) 表示调用0地址处的无参且返回值为void的函数;
注:0地址不允许用户程序访问,该行代码运行会抛异常;
1.2 示例2
void ( *signal (int, void(*) (int) ) )(int);
(1)void(*) (int) 表示以一个int型为参数且返回值为void的函数指针变量;
(2)signal (int, void(*) (int) ) 表示两个参数分别为int型和函数指针型的,名为signal的函数;
(3)void (* )(int)表示以一个int型为参数且返回值为void的函数指针变量;
注:挖去(2)中已分析部分,得到void ( * )(int);
(4)void ( *signal (int, void(*) (int) ) )(int) 等价于void (* )(int) signal (int, void(*) (int) ),
(该写法是错误的,但可更直观理解该行代码的功能)
即:声明了一个名为signal的函数,该函数有两个参数,一个为int型,一个为函数指针变量,
并且该函数的返回值也是函数指针类型;
2. typedef 用法
2.1 简单类型重命名
#include<stdio.h>
typedef unsigned int u_int;
typedef int* pint_t;
int main() {
// 以下两行等价
unsigned int a1;
u_int a2;
// 以下两行等价
int* b1;
pint_t b2;
return 0;
}
2.2 复杂指针类型重命名
2.2.1 数组指针类型
#include<stdio.h>
typedef int(*pa_t)[5];
int main() {
int arr[5] = { 1,2,3,4,5 };
int(*pa1)[5] = &arr;
pa_t pa2 = &arr;
printf("pa1 = %p\n", pa1);
printf("pa2 = %p\n", pa2);
return 0;
}
运行结果如下:
注:按照标准格式应写为:typedef int(*)[5] pa_t,但对于数组指针类型,需将重命名后的类型名移至括号内的*边:typedef int(*pa_t)[5];
2.2.2 函数指针类型
#include<stdio.h>
typedef int(*pf_t)(int, int);
int Add(int x, int y) {
return x + y;
}
int main() {
int(*pf1)(int, int) = &Add;
pf_t pf2 = &Add;
printf("pf1 = %p\n", pf1);
printf("pf2 = %p\n", pf2);
return 0;
}
运行结果如下:
注:按照标准格式应写为:typedef int(*)(int, int) pf_t,但对于数组指针类型,需将重命名后的类型移至括号内的*边:typedef int(*pf_t)(int, int);
3. 使用typedef简化复杂类型的定义
(回归示例1与示例2,对应简化)
#include<stdio.h>
typedef void(*pf_t)();
int main() {
// ( * (void (*) () ) 0 )();
((pf_t)0)();
// void ( *signal (int, void(*) (int) ) )(int);
pf_t signal(int, pf_t);
return 0;
}
4. #define与typedef
#include<stdio.h>
#include<stdlib.h>
typedef int* pint_t;
#define PINT_T int*
int main() {
pint_t p1, p2;
// p1 p2都是指针变量
PINT_T p3, p4;
// p3是指针变量,p4是整型变量
return 0;
}
调试借助监视窗口查看变量类型:
理解#define与typedef的区别:
(1)int*一经typedef为pint_t,所有int*会被替换为int*:
pint_t p1, p2;
// 即处理为:
// int* p1; int* p2;
(2)#define仅仅实现了符号PINT_T等价为int*:
PINT_T p3, p4;
// 即处理为:
// int* p3,p4;
// 即:int *p3; int p4;
仅将*分配给p3,即将p3定义为int*型,p4定义为int型;