typedef与define都是替一个对象取一个别名,以此来增强程序的可读性,但是它们在使用和作用上也存在着以下几个方面的不同:

1) 原理不同。

#define是C语言中定义的语法,它是预处理指令,在预处理时进行简单而 机械的字符串替换,不做正确性检查,不管含义是否正确照样带入,只有在编译己被展开的源程序时才会发现可能的错误并报错。

例如,#defme PI 3.1415926,当程序中执行area=PI*r*r语句时,PI会被替换为 3.1415926,于是该语句被替换为area=3.1415926*r*i•。如果把#defme语句中的数字9写成了g,预处理也照样带入,而不去检查其是否合理、合法。

typedef是关键字,它在编译时处理,所以typedef有类型检查的功能。它在自己的作用域内给一个已经存在的类型一个别名,但是不能在一个函数定义里面使用标识符typedef。例 如,typedefint INTEGER,这以后就可用INTEGER来代替int作整型变量的类型说明 了,如:

INTEGER a, b;

用typedef定义数组、指针、结构等类型将带来很大的方便,不仅使程序书写简单而且使 意义更为明确,因而增强了可读性。例如:

typedef int a[10];

表示a是整型数组类型,数组长度为10。然后就可用a说明变量,如a s1,S2;完全等效于 int sl[10],s2[10]。同理,typedef void (*p)(void)表示 p 是一种指向 void 型的指针类型。

2) 功能不同。

typedef用来定义类型的别名,这些类型不只包含内部类型(int、char等),还包括自定义类型(如struct),可以起到使类型易于记忆的功能。例如:

typedef int (*PF) (const char *,const char *);

定义一个指向函数的指针的数据类型PF,其中函数返回值为int,参数为const char *。

typedef还有另外一个重要的用途,那就是定义机器无关的类型。例如,可以定义一个叫 REAL的浮点类型,在目标机器上它可以获得最高的精度:typedef long double REAL,在不支持long double的机器上,该typedef看起来会是下面这样:typedef double REAL,在double都不支持的机器上,该typedef看起来会是这样:typedef float REAL。

#define不只是可以为类型取别名,还可以定义常量、变量、编译开关等。

3) 作用域不同。

#defme没有作用域的限制,只要是之前预定义过的宏,在以后的程序中都可以使用,而typedef有自己的作用域。

程序示例如下:

1
2
3
4
5
6
7
8
9
void fun()
{
	#define A int
}
void gun()
{
//在这里也可以使用A,因为宏替换没有作用域,但如果上面用的是typedef,那这里就不能用
//A,不过一般不在函数内使用typedef
}

4) 对指针的操作不同。

两者修饰指针类型时,作用不同。

1
2
3
4
#defme INTPTR1 int*
typedefint* INTPTR2;
INTPTR1 p1,p2;
INTPTR2 p3,p4;

INTPTR1 pl,p2和INTPTR2 p3,p4这两句的效果截然不同的。

INTPTR1 p1,p2进行字符串替换后变成int* p1,p2,要表达的意义是声明一个指针变量p1和一个整型变量P2。而INTPTR2 p3,p4,由于INTPTR2是具有含义的,告诉我们是一个指向整型数据的指针,那么p3和P4都为指针变量,这句相当于int* p1,*P2。从这里可以看出,进行宏替换是不含任何意义的替换,仅仅为字符串替换;而用typedef为一种数据类型起的别名是带有一定含义的。

程序示例如下:

1
2
3
4
5
6
7
8
#define INTPTR1 int*
typedef int* INTPTR2;
int a=1;
int b=2;
int c=3;
const INTPTR1 p1=&a;
const INTPTR2 p2=&b;
INTPTR2 const p3=&c;

const INTPTR1 p1表示p1是一个常量指针,即不可以通过p1去修改p1指向的内容,但是p1可以指向其他内容。

const INTPTR2 p2,由于INTPTR2表示是一个指针类型,因此用const去限定,表示封锁了这个指针类型,因此p2是一个指针常量,不可使p2再指向其他的内容,但可以通过p2修改其当前指向的内容。INTPTR2 const p3同样声明的是一个指针常量。