typedef用法总结

来源:互联网 发布:淘宝客微信小程序效果 编辑:程序博客网 时间:2024/06/17 09:04

1、问题引入:
   接触了typedef多时,对它的了解是:用来声明一个别名,typedef后面的语法,是一个声明。
   其实,他同define的差别是比较大的,不仅仅是替换问题。
   如下
  typedef int a[10]; typedef void (*p)(void)
  typedef int Fun() ;
  用上面的概念能解释了吗?是用a[10]来代替Int吗?答案是NO!
  2、别人的解释:
  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);
  }
  3、我的理解
  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型的函数了。
  下面对typedef作较为详细准备的解释:
  
  2)使用 typedef为现有类型创建同义字。 定义易于记忆的类型名 
  
  typedef原类型名 替换类型名; 
  
  如typedef int me;
  
   me a;
  
  typedef 还可以掩饰符合类型,如指针和数组。
  
  char line[81]; 
  
  定义一个 typedef,如下示: 
  
  typedef char Line[81]; 
  
  Line text, secondline; 
  
  getline(text); 
  
  typedef struct tagNode 
  
  { 
  
   char *pItem; 
  
   pNode pNext; 
  
  } *pNode; //这样,pNode就相当于struct tagNode *;
  
  pNode p; 
  
  同样,可以象下面这样隐藏指针语法: 
  
  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(或任何其它存储类关键字)


原创粉丝点击