typedef与函数指针
typedef 为一种类型引入新的名字,而不是为变量分配空间。在某些方面,typedef 类似于宏文本替换——它并没有引入新的类型,而是为现有类型取个新名字,但和文本替换之间有着关键性区别。
一般情况下,typedef用于简洁地表示指向其他东西的指针。典型的例子是signal()原型的声明。signal()是一种系统调用,用于通知运行时系统,当某种特定的“软件中断”发生时调用特定的程序。通过调用signal(),并通过参数传递告诉中断的类型以及用于处理中断的函数。
下面是signal()的声明:
一般情况下,typedef用于简洁地表示指向其他东西的指针。典型的例子是signal()原型的声明。signal()是一种系统调用,用于通知运行时系统,当某种特定的“软件中断”发生时调用特定的程序。通过调用signal(),并通过参数传递告诉中断的类型以及用于处理中断的函数。下面是signal()的声明:
void (*signal(int sig,void(*func)(int)))(int);
signal是一个函数,它返回一个函数指针,后者所指向的函数接受一个int参数并返回void。其中一个恐怖的参数是其本身:
void (*func)(int);
它表示一个函数指针,所指向的函数接受一个int参数,返回值是void。下面通过typedef来“简化”一下:
typedef void(*ptr_to_func) (int);
/*它表示ptr_to_func是一个函数指针,该函数接受一个int参数,返回值为void*/
ptr_to_func signal(int,ptr_to_func);
/*它表示signal是一个函数,它接受两个参数,其中一个是int,另一个是ptr_to_func,返回值是ptr_to_func*/
typedef 与结构体
C语言中存在多种名字空间:
- 标签名
- 标签:这个名字空间用于所有的结构、枚举和联合
- 成员名:每个结构或联合都有自身的名字空间
- 其他
在同一个名字空间里,任何名字必须具有唯一性,但在不同的名字空间里可以存在相同的名字。由于每个结构或联合具有自己的名字空间,所以同一个名字可以出现在许多不同的结构内。
下面两个声明具有相似的形式:
typedef struct fruit {
int weight;
double price_per_lb;
}fruit;
struct veg{
int weight;
double price_per_lib;
}veg;
但它们代表的意思完全不一样,语句1声明了结构标签“fruit”和由typedef 声明的结构类型“fruit”,其实际效果如下:
struct fruit mandarin; //使用结构标签“fruit”
fruit mandarin; //使用结构类型“fruit”
语句2声明了结构标签“veg”和变量“veg”。只有结构标签能够在以后的声明中使用,如,
struct veg potato;
如果试图使用veg cabbage这样声明,将是一个错误。这类似于下面的写法:
int i;
i j;
typedef 与 #define
typedef 和宏文本替换之间存在一个关键性区别。具体体现在两个方面:
首先,可以用其他类型说明符对宏类型名进行扩展,但对typedef 所定义的类型名却不能这样做。如下所示:
#define peach int
unsigned peach i; //没问题
typedef int banan;
unsigned banan i; //错误,非法
其次,在连续几个变量的声明中,用typedef 定义的类型能够保证声明中所有的变量均为同一类型,而用#define 定义的类型则无法保证。
#define int_ptr int*
int_ptr chalk, cheese;
经过宏扩展,第二行变为:
int * chalk, cheese;
这使得chalk和cheese成为不同的类型,chalk 是一个指向int 的指针,而cheese 则是一个int。相反,
typedef char * char_ptr;
char_ptr bent, rolld;
bent和rolld 的类型相同。它们都是指向char的指针。