本文参考网络资料,相关博客链接如下:
http://c.biancheng.net/view/298.html
typedef:重新定义一种数据类型(或者是给类型起别名)。 C语言允许用户使用 typedef 关键字来定义自己习惯的数据类型名称,来替代系统默认的基本类型名称、数组类型名称、 指针类型名称与用户自定义的结构型名称、共用型名称、枚举型名称等。一旦用户在程序中定义了自己的数据类型名称, 就可以在该程序中用自己的数据类型名称来定义变量的类型、数组的类型、指针变量的类型与函数的类型等。
typedef的用法: 1.为基本数据类型定义新的类型名: typedef unsigned int uint32 1.1 也就是说,系统默认的所有基本类型都可以利用 typedef 关键字来重新定义类型名 1.2 我们还可以使用这种方法来定义与平台无关的类型。 比如,要定义一个叫 REAL 的浮点类型,在目标平台一上,让它表示最高精度的类型, 即:typedef long double REAL; 当跨平台移植程序时,甚至还可以在连 double 都不支持的平台上,我们只需要修改一下 typedef 的定义即可, 而不用对其他源代码做任何修改。 其实,标准库中广泛地使用了这个技巧,比如 size_t 在 VC++2010 的 crtdefs.h 文件中的定义如下所示: #ifndef _SIZE_T_DEFINED #ifdef _WIN64 typedef unsigned __int64 size_t; #else typedef _W64 unsigned int size_t; #endif #define _SIZE_T_DEFINED #endif
2. 为自定义数据类型(结构体、共用体和枚举类型)定义简洁的类型名称 以结构体为例,下面我们定义一个名为 Point 的结构体:
struct Point { double x; double y; double z; };
在调用这个结构体时,我们必须像下面的代码这样来调用这个结构体:
struct Point oPoint1={100,100,0}; struct Point oPoint2;
在这里,结构体 struct Point 为新的数据类型,在定义变量的时候均要向上面的调用方法一样有保留字 struct, 而不能像 int 和 double 那样直接使用 Point 来定义变量。 现在,我们利用 typedef 定义这个结构体,如下面的代码所示:
typedef struct tagPoint { double x; double y; double z; } Point;
因此,现在你就可以像 int 和 double 那样直接使用 Point 定义变量,如下面的代码所示:
Point oPoint1={100,100,0}; Point oPoint2;
结构中包含指向它自己的指针
struct tagNode { char *pItem; struct tagNode *pNext; }; typedef struct tagNode *pNode;
3. 为数组定义简洁的类型名称 typedef int INT_ARRAY_100[100]; INT_ARRAY_100 arr;
4. 为指针定义简洁的名称 typedef char* PCHAR; PCHAR pa;
// PFun是我们创建的一个类型别名 typedef int *(*PFun)(int,char*); // 使用定义的新类型来声明对象,等价于int*(*a[5])(int,char*); PFun a[5];
#define与typedef的区别和用法:
1、宏替换: 只能用#define了,比如:#define PI 3.14
2、给简单数据类型起别名: 2.1 #define uint32 unsigned int 2.2 typedef unsigned int uint32 //其实这两个是一样的。
3、声明一个指向简单数据类型变量的指针 3.1 #define uint32_p unsigned int * 如果我们只用来声明一个指针变量是没问题的,但是要是出现这样一种情况:uint32_p p1,p2; 结果会怎样呢? 根据#define替换的功能,可以解析成 unsigned int *p1,p2; 而这个声明的作用与我们之前的目的是完全不一样了吧。 3.2 typedef unsigned int* uint32_p uint32_p,是一种新的数据类型,完全可以用它去声明uint32_p p1,p2;
4、结构体类型的声明: typedef struct{ uint32 a; uint16 *p; uint16 array[10]; }m_T; 我们可以直接用m_T声明结构体变量;m_T m1,*m2; 而且我们可以把这个声明放在一个头文件里,方便其它想使用这个声明的地方。 这里要是换成用#define实现会怎样呢?你可以试试一下
5、我们看这样一个表达式,也是学习指针(函数指针、指针函数)最为经典的例子: (*( void (*)() )0)(); //硬件地址跳到0处 void(*)() :是一个函数指针类型的声明,声明了一个指向返回值类型为void的函数的函数指针, 假设fp是一个函数指针,那么如何调用fp所指向的函数,调用方法如下: (*fp)(); 要是从硬件的0地址启动,似乎(*0)();就可以调用指向0地址的函数。但是,这样是无效的。fp必须是一个指针 现在就可以把“0”强制转换成函数指针类型,: ( void (*)() )0 现在(* ( void (*)() )0 )(); //外部调用一个函数指针,函数指针是 void (*)()型的函数指针 如果在程序的其它地方也会用到void (*)(), 我们是不是考虑一下,用typedef void(*)() A 当再要定义返回值类型为void类型的函数指针时只用写: A a;, 之前的例子就可以写作:(*(A)0)(); 如果换成#define void (*)() A,是不会也能实现这个效果呢?
写到这里我要借助C陷阱与缺陷里的内容了,请大家自己理解:
使用 typedef 的目的 or 好处:
1、为了隐藏特定类型的实现,强调类型的使用目的 2、允许一种类型用于多个目的,同时使得每次使用给类型的目的明确 如:typedef int (*Function)(const char *, const char *);
该定义表示 Function 是一种指向函数的指针的类型的别名, 要使用这种指针类型时只需直接使用 Function即可, 不必每次把整个声明都写出来
void (*Signal(int,void(*)(int)))(int);
typedef void (*HANDLER)(int);
HANDLER Signal(int,HANDLER); 上下两种声明意义是一致的 |