Point 2 typedef
与define
从上小点讨论认为define为标识符代换使用。下面的例子您肯定很清楚:
#define SQU(x) ((x)*(x)) //
定义((x)*(x))为SQU(x),编译器遇到SQU(x)后自动替换为((x)*(x))。
typedef
针对类型的重命名而言的。看下例:
typedef struct ITEM{
char filename[ FILE_NAME_MAX_LEN + 1 ];
char path[ PATH_MAX_LEN + 1 ];
FILE_T type;
long totalLine;
long commentLine;
long bankLine;
long codeLine;
}ITEM, *PITEM;
将结构体
ITEM
定义(重命名)为
ITEM
,以及
struct ITEM*
定义为
PITEM
。这样做的好处是有助于使代码清晰,简记类型。
或者:
typedef int BOOL;
注意:句后带分号,不同于宏。typedef 为类型定义,本质上区别于define宏定义。
Point 3
函数指针
指针总是跟地址和映射联系起来的,它代表一种间接访问的方式。首先,它以变量形式出现(变量指针,函数指针,常量指针);其次,依据其内容,对其内容的映射——通常是另一个对象——进行访问。
顾名思义,函数指针也是一种提供间接访问方式的变量,在C/C++中表现为函数名或函数地址。也可以这样理解:借用ASM里的代码段的概念,函数既是一段特定功能的代码的封装,载入内存后是有入口可供访问的。这个入口就是它的地址,即指针。
考虑下面的例子:
typedef BOOL ( *CMP )( void* _a, void* _b );
可以先忽略掉typedef,看余下部分。它的意思是:定义一个名为CMP的变量,
它(的内容)指向原型为BOOL xxx(void* _a, void* _b )的函数。加上typedef后,意思是:定义CMP为指向返回值为BOOL,带两个void*参数的函数原型的指针类型。
我们可以这样来实例化:
CMP pfObject; // a variable pfObject which type is CMP
我们通常会遇到这样的情形:当对一个表或某种数据结构进行遍历操作的时候,往往对数据操作各不相同,但遍历的次序及对象是一样的,而且我们也为这样的实现写过很多相似的遍历代码。那种无意义重复是很烦人的。我们就想,把对数据的操作传到遍历操作里面,由传递的数据操作参数决定对遍历对象的操作,那不就省事了!无疑,这时用函数指针是不错的选择。请看下面的例子:
BOOL FindNext(CLIST *cl,
CLISTLINK **pFind,
void *value,
CMP cmp);
(FindNext是一个依据
CLISTLINK **pFind
提供的位置信息以及外部比较值
value
,使用
CMP cmp
指定的比较方法在
CLIST *CL
里进行查找的函数。当找到与
value
匹配值返回
TRUE
,并将此位置从
pFind
带出。否则返回
FALSE
。)
该函数内对每个数据对象的操作应该是:
cmp( value, (each object of clist))
结果返回
BOOL
值。或者我们可以这样声明该函数:
BOOL FindNext(CLIST *cl,
CLISTLINK **pFind,
void *value,
BOOL ( *cmp )( void* _a, void* _b ));
两种声明是等价的,取决于个人习惯。
请您思考为什么等价。