c/c++ 之typedef的用法

论坛 期权论坛 编程之家     
选择匿名的用户   2021-5-30 12:41   33   0

本文参考网络资料,相关博客链接如下:

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);
上下两种声明意义是一致的

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:3875789
帖子:775174
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP