14、typedef 用法总结

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能隐藏笨拙的语法构造以及平台相关的数据类型,从而增强可移植性和以及未来的可维护性。

发布了288 篇原创文章 · 获赞 31 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/hopegrace/article/details/104589148