要命的typedef, 之前总觉的typedef和#define很相似,但是肯定是有差异的对吧,先举个例子看看他们的差别。
#define Int_t int
unsigned Int_t i;
typedef int Int_w;
unsigned Int_w i;
首先看unsigned Int_t i;这个肯定是正确的,因为就等同于unsigned int i;而后者 unsigned Int_w i;会报错,因为typedef会保证定义的类型声明的变量类一致,这明显与unsigned 这个前缀相冲突。只要将unsigned 去掉就可以通过编译。
#define int_t int *
typedef int * int_w;
int_t a, b;
int_w c, d;
分解int_t a,b; 可以得到 int * a,b; 然而分解int_w c,d; 可以得到 int * c;int *d;
以上的例子可以很明显看到typedef和define的区别;
然后来看下一个例子
void(*signal(int sig, void(*func)(int)))(int);
怎么用typedef将该函数进行分解呢?
先将void(*func)(int)单独拿出来。
首先看func是什么?一个指针,指向什么?指向一个返回值是void并且还有一个int参数的函数。
接下来不妨将typedef void(*func)(int);
然后将
void(*signal(int sig, void(*func)(int)))(int);
进行替换操作
第一步结果如下 void(*signal(int sig,func))(int);
第二步结果如下 func signal(int,func);
不要想到多,func这里只是一个小指针。
走到这步怎么再让你的程序再难度一点呢?对糟糕的命名方式。
如下个例子
struct foo{ int foo; }foo;
标签,成员名,对象名,嗯很好这样就肆无忌惮的通过编译器的安检。
那就再恶心一点吧。
typedef struct baz{ int baz; } baz;
struct baz a;//使用结构体标签
baz b;//使用结构体类型
没错,编译器安检照样过。
为了区分以上两位大佬我们可以将名称稍微做一下变化,变化如下
typedef struct baz{ int baz_t; }baz_w;
那么baz_w a;照样能通过安检,因为typedef引入baz_w时同样引入了baz结构体标签;
若是将改成
struct baz{ int baz_t; }baz_w;
baz_w a;这样毫不犹豫就会报错,这个就像
int a;a b;的错误一致。