1、typedef使用示例
typedef int a[10]; typedef void (*p)(void)
typedef int Fun();
定义了一个函数类型Fun,所有这个类型的函数都返回一个int类型的值。
再如:
int sum(int a, int b)
{
return (a + b);
}
int sub(int a, int b)
{
return (a - b);
}
typedef int CalcType(int a, int b); //这样CalcType就成了返回值为int型,接受参数为两个整数的函数。
int main()
{
int select = -1;
int result;
int a;
int b;
CalcType calculate[] = {sum, sub};
printf("Please select calculation type\n");
scanf("%d\n", select);
printf("Input two value\n");
scanf("%d %d\n", &a, &b);
if (select == 0 || select == 1)
result = calculate[select](a, b);
return (0);
}
2、使用解释
1)示例
int a[20]<=>int[] a=new int[20] //意思是开辟int型的20个地址空间给a,a的类型是a[]。
typedef char sstring[MAX]<=>typedef char[MAX] sstring //这样,sstring就可以定义一维字符型数组了。
如:sstring s1<=>char s1[MAX]。
这样,我们再理解刚才上面提到的问题:
typedef int a[10]<=>typedef int[10] a //也就是说a可以去定义一唯整形数组了。
typedef void (*p)(void) <=>typedef void(*)(void) p //可以用p去定义指向返回值为空值,参数也为空值的函数了。
typedef int Fun() <=> typedef int() Fun //意思是Fun可以去定义返回值为int型的函数了。
总之,相当于定义别名,其值为表达式中除去新别名后的表达式。
2)使用typedef为现有类型创建同义字,定义易于记忆的类型名
typedef原类型名 替换类型名;
typedef char * pstr;
int mystrcmp(pstr, pstr);
注意:标准函数 strcmp()有两个‘const char *'类型的参数。 ‘const pstr'被解释为‘char * const'(一个指向 char的常量指针),而不是‘const char *'(指向常量 char的指针)。
typedef const char * cpstr;
int mystrcmp(cpstr, cpstr); //现在是正确的
记住:不管什么时候,只要为指针声明 typedef,那么都要在最终的 typedef名称中加一个const,以使得该指针本身是常量,而不是对象。
3)代码简化
上面讨论的typedef行为有点像 #define宏,用其实际类型替代同义字。不同点是 typedef在编译时被解释,因此让编译器来应付超越预处理器能力的文本替换。例如:
typedef int (*PF) (const char *, const char *);
这个声明引入了 PF类型作为函数指针的同义字,该函数有两个 const char *类型的参数以及一个 int类型的返回值。
再如一下面的三个例子(将复杂的式子用typedef简化):
对复杂变量建立一个类型别名的方法很简单,你只要在传统的变量声明表达式里用类型名替代变量名,然后把关键字typedef加在该语句的开头就行了。
(1)int *(*a[5])(int, char*);如下转化表达:
typedef int *(*pFun)(int, char*); //pFun是我们建的一个类型别名
pFun a[5]; //使用定义的新类型来声明对象,等价于int* (*a[5])(int, char*);
(2)void (*b[10])(void (*)());
typedef void (*pFunParam)(); //首先为上面表达式斜体加粗部分声明一个新类型
typedef void (*pFun)(pFunParam); //整体声明一个新类型
pFun b[10]; //使用定义的新类型来声明对象,等价于void (*b[10]) (void (*)());
(3)doube(*)() (*pa)[9]; //首先为上面表达式斜体加粗部分声明一个新类型
typedef double(*pFun)(); //整体声明一个新类型
typedef pFun (*pFunParam)[9]; //使用定义的新类型来声明对象,等价于doube(*)() (*pa)[9];
pFunParam pa;
4)促进跨平台开发
typedef有另外一个重要的用途,那就是定义机器无关的类型,例如,你可以定义一个叫REAL的浮点类型,在目标机器上它可以自动获得最高的精度:
typedef long double REAL;
在不支持 long double的机器上,该 typedef看起来会是下面这样:
typedef double REAL;
并且,在连 double都不支持的机器上,该 typedef看起来会是这样:
typedef float REAL;
在大多数情况下,甚至这个微小的变动完全都可以通过奇妙的条件编译来自动实现。标准库广泛地使用 typedef来创建这样的平台无关类型:
size_t,ptrdiff和 fpos_t就是其中的例子。此外,象 std::string和 std::ofstream这样的 typedef还隐藏了长长的,难以理解的模板特化语法,例如:basic_string,allocator>和 basic_ofstream>。
5)typedef与#define的比较
(A)他们的不同:
我们以例子进行。
例一:
typedef char *pStr;
#define pStr char *;
通常讲,typedef要比#define要好,特别是在有指针的场合:
typedef char *pStr1;
#define pStr2 char *;
pStr1 s1, s2;
pStr2 s3, s4;
在上述的变量定义中,s1、s2、s3都被定义为char *,而s4则定义成了char,不是我们所预期的指针变量,根本原因就在于#define只是简单的字符串替换而typedef则是为一个类型起新名字。
#define用法的一个例子:
#define f(x) x*x
main( )
{
int a=6,b=2,c;
c=f(a) / f(b);
printf("%d \\n",c);
}
以下程序的输出结果是: 36,出错。
在许多C语言编程规范中提到使用#define定义时,如果定义中包含表达式,必须使用括号:#define f(x) (x*x),这样才有正确结果。当然,使用typedef就没有这样的问题。
例二:
下面的代码中编译器会报一个错误,你知道是哪个语句错了吗?
typedef char * pStr;
char string[4] = "abc";
const char *p1 = string;
const pStr p2 = string;
p1++;
p2++;
是p2++出错了。上述代码中const pStr p2并不等于const char * p2,不是简单的替换。const pStr p2和const long x本质上没有区别,都是对变量进行只读限制,只不过此处变量p2的数据类型是我们自己定义的而不是系统固有类型而已。因此,const pStr p2的含义是:限定数据类型为char *的变量p2为只读,因此p2++错误。
(B)#define与typedef引申谈
1) #define宏定义的特别长处:可使用 #ifdef ,#ifndef等来进行逻辑判断,使用#undef来取消定义。
2) typedef的特别长处:它符合范围规则,使用typedef定义的变量类型其作用范围限制在所定义的函数或者文件内(取决于此变量定义的位置),而宏定义则没有这种特性。
6)typedef与存储关键字
typedef就像 auto,extern,mutable,static,和 register一样,是一个存储类关键字。这并不是说 typedef会真正影响对象的存储特性;它只是说在语句构成上,typedef声明看起来象 static,extern等类型的变量声明。
第二个陷阱:
typedef register int FAST_COUNTER; //错误
编译通不过。问题出在你不能在声明中有多个存储类关键字。因为符号 typedef已经占据了存储类关键字的位置,在 typedef声明中不能用 register(或任何其它存储类关键字)。
4、static
static修饰变量和修饰函数的意义是不同的(作用域与生成期)。
修饰变量是把该变量的作用与限制在某一范围内,这个范围可以是模块范围、函数范围、类范围、复合语句范围,但其生存期从进入其有效范围开始到程序运行结束。
static修饰函数时,是把这个函数的有效范围限制在定义他的模块内。
typedef声明有助于创建平台无关类型,甚至能隐藏复杂和难以理解的语法。
typedef声明,简称 typedef,为现有类型创建一个新的名字。比如人们常常使用 typedef来编写更美观和可读的代码。所谓美观,意指 typedef能隐藏笨拙的语法构造以及平台相关的数据类型,从而增强可移植性和以及未来的可维护性。