iOS开发基础篇

typedef的用法

2017-06-02  本文已影响55人  Cheriez

一、基本定义

typedef为C语言的关键字,作用是为一种数据类型定义一个新名字。这里的数据类型包括内部数据类型(int,char等)和自定义的数据类型(struct等)。

很多初学者只知道typedef char* pchar;但是对于typedef的其它用法不太了解。Stephen Blaha对typedef用法做过一个总结:“建立一个类型别名的方法很简单,在传统的变量声明表达式里用类型名替代变量名,然后把关键字typedef加在该语句的开头”。

二、用途

char* pa, pb; // 这多数不符合我们的意图,它只声明了一个指向字符变量的指针,  
// 和一个字符变量;  

以下则可行

typedef char* PCHAR;  
PCHAR pa, pb;    

这种用法很有用,特别是char* pa, pb的定义,初学者往往认为是定义了两个字符型指针,其实不是,而用typedef char* PCHAR就不会出现这样的问题,减少了错误的发生。

struct tagPOINT1  
 {  
    int x;  
    int y;   
};  
struct tagPOINT1 p1;  

而在C++中,则可以直接写:结构名对象名,即:tagPOINT1 p1;

typedef struct tagPOINT  
{  
    int x;  
    int y;  
}POINT;  

POINT p1; // 这样就比原来的方式少写了一个struct,比较省事,尤其在大量使用的时候,或许,在C++中,typedef的这种用途二不是很大,但是理解了它,对掌握以前的旧代码还是有帮助的,毕竟我们在项目中有可能会遇到较早些年代遗留下来的代码。

typedef long double REAL;   

在不支持 long double 的机器上,该 typedef 看起来会是下面这样:

typedef double REAL;   

并且,在连 double 都不支持的机器上,该 typedef 看起来会是这样:

typedef float REAL;   

也就是说,当跨平台时,只要改下 typedef 本身就行,不用对其他源码做任何修改。
标准库就广泛使用了这个技巧,比如size_t。另外,因为typedef是定义了一种类型的新别名,不是简单的字符串替换,所以它比宏来得稳健。

char line[81];  
char text[81];   

定义一个 typedef,每当要用到相同类型和大小的数组时,可以这样:

typedef char Line[81];   

此时Line类型即代表了具有81个元素的字符数组,使用方法如下:

Line text, secondline;  
getline(text);   

同样,可以象下面这样隐藏指针语法:

typedef char * pstr;  
int mystrcmp(pstr, pstr);  

这里将带我们到达第一个 typedef 陷阱。标准函数 strcmp()有两个‘ const char *'类型的参数。因此,它可能会误导人们象下面这样声明 mystrcmp():

int mystrcmp(const pstr, const pstr);   

这是错误的,事实上,const pstr被编译器解释为char * const(一个指向 char 的常量指针),而不是const char *(指向常量 char 的指针)。
这个问题很容易解决:

typedef const char * cpstr; 
int mystrcmp(cpstr, cpstr);

这里涉及到const的知识,我说明下。
类型声明中const用来修饰一个常量,我们一般这样使用:const在前面:

const int; //int是const
const char*;//char是const 
char* const;//*(指针)是const 
const char* const;//char和*都是const 

对初学者,const char * 和 char * const是容易混淆的。这需要时间的历练让你习惯它。 上面的声明有一个对等的写法:const在后面:

int const; //int是const 
char const*;//char是const 
char* const;//*(指针)是const 
char const* const;//char和*都是const

const在后面有两个好处:
A.const所修饰的类型正好是在它前面的那一个。如果这个好处还不能让你动心的话,那请看下一个!
B.我们很多时候会用到typedef的类型别名定义。比如typedef char* pchar,如果用const来修饰的话,当const在前面的时候,就是const pchar,你会以为它就是const char* ,但是你错了,它的真实含义是char* const。
是不是让你大吃一惊!但如果你采用const在后面的写法,意义就怎么也不会变,不信你试试!

void (*b[10]) (void (*)());  

变量名为b,先替换右边部分括号里的,pFunParam为别名

typedef void (*pFunParam)();  

再替换左边的变量b,pFunx为别名二:

typedef void (*pFunx)(pFunParam);  

原声明的最简化版:

pFunx b[10];  

理解复杂声明可用的“右左法则”:从变量名看起,先往右,再往左,碰到一个圆括号就调转阅读的方向;括号内分析完就跳出括号,还是按先右后左的顺序,如此循环,直到整个声明分析完。

typedef register int FAST_COUNTER; // 错误  

编译通不过。问题出在你不能在声明中有多个存储类关键字。因为符号 typedef 已经占据了存储类关键字的位置,在 typedef 声明中不能用 register(或任何其它存储类关键字)。

上一篇下一篇

猜你喜欢

热点阅读