zoukankan      html  css  js  c++  java
  • typedef的用法和相关问题

    用了C和C++这么久,今天才仔细研究了下typedef的用法,真的是惭愧啊,不过基础都是不断巩固的啊。

    typedef

    在计算机编程语言中用来为复杂的声明定义简单的别名,与宏定义有些差异。它本身是一种存储类的关键字,与auto、extern、mutable、static、register等关键字不能出现在同一个表达式中。

    1. typedef和结构体问题

    当用下面的代码定义一个结构时,编译器报了一个错误,为什么呢?莫非C语言不允许在结构中包含指向它自己的指针吗?请你先猜想一下,然后看下文说明:

    1 typedef struct tagNode
    2 {
    3  
    4   char* pItem;
    5  
    6   pNode pNext;
    7  
    8 }*pNode;

    举个例子:

    1 typedef struct tagMyStruct
    2 {
    3  
    4    int iNum;
    5  
    6    long lLength;
    7  
    8  
    9 }MyStruct;
    这语句实际上完成两个操作:
    1) 定义一个新的结构类型
    1 struct tagMyStruct
    2 {
    3  
    4     int iNum;
    5  
    6  
    7     long lLength;
    8  
    9 };
    分析:tagMyStruct称为“tag”,即“标签”,实际上是一个临时名字,struct关键字和tagMyStruct一起,构成了这个结构类型,不论是否有typedef,这个结构都存在。
    我们可以用struct tagMyStruct varName来定义变量,但要注意,使用tagMyStruct varName来定义变量是不对的,因为struct 和tagMyStruct合在一起才能表示一个结构类型。
    2) typedef为这个新的结构起了一个名字,叫MyStruct。
    typedef struct tagMyStruct MyStruct;
    因此,MyStruct实际上相当于struct tagMyStruct,我们可以使用MyStruct varName来定义变量。
    答案与分析
    C语言当然允许在结构中包含指向它自己的指针,我们可以在建立链表等数据结构的实现上看到无数这样的例子,上述代码的根本问题在于typedef的应用。
    根据我们上面的阐述可以知道:新结构建立的过程中遇到了pNext域的声明,类型是pNode,要知道pNode表示的是类型的新名字,那么在类型本身还没有建立完成的时候,这个类型的新名字也还不存在,也就是说这个时候编译器根本不认识pNode。

    2. typedef和define的区别

    有下面两种定义pStr数据类型的方法,两者有什么不同?哪一种更好一点?

    1 typedef char* pStr;
    2  
    3 #define pStr char*
    答案与分析:
    通常讲,typedef要比#define要好,特别是在有指针的场合。请看例子:
    1 typedef char* pStr1;
    2  
    3 #define pStr2 char* 
    4  
    5 pStr1 s1,s2;
    6  
    7 pStr2 s3,s4;
    在上述的变量定义中,s1、s2、s3都被定义为char *,而s4则定义成了char,不是我们所预期的指针变量,根本原因就在于#define只是简单的字符串替换而typedef则是为一个类型起新名字。
    上例中define语句必须写成 pStr2 s3, *s4; 这样才能正常执行。

    3.  const问题

    下面的代码中编译器会报一个错误,你知道是哪个语句错了吗?

    1 typedef char *pStr;
    2 char string[4]="abc";
    3 const char *p1=string;
    4 const pStr p2=string;
    5 p1++;
    6 p2++;
    答案与分析:
    是p2++出错了。这个问题再一次提醒我们:typedef和#define不同,它不是简单的文本替换。上述代码中const pStr p2并不等于const char * p2。const pStr p2和pStr const p2本质上没有区别,都是对变量进行只读限制,只不过此处变量p2的数据类型是我们自己定义的而不是系统固有类型而已。因此,const pStr p2的含义是:限定数据类型为char *的变量p2为只读,因此p2++错误。
    #define与typedef引申谈
    1) #define宏定义有一个特别的长处:可以使用 #ifdef ,#ifndef等来进行逻辑判断,还可以使用#undef来取消定义。
    2) typedef也有一个特别的长处:它符合范围规则,使用typedef定义的变量类型其作用范围限制在所定义的函数或者文件内(取决于此变量定义的位置),而宏定义则没有这种特性。

    4. tyepdef和复杂的变量声明

    理解复杂声明可用的“右左法则”:
      从变量名看起,先往右,再往左,碰到一个圆括号就调转阅读的方向;括号内分析完就跳出括号,还是按先右后左的顺序,如此循环,直到整个声明分析完。举例:
      int (*func)(int *p);
      首 先找到变量名func,外面有一对圆括号,而且左边是一个*号,这说明func是一个指针;然后跳出这个圆括号,先看右边,又遇到圆括号,这说明 (*func)是一个函数,所以func是一个指向这类函数的指针,即函数指针,这类函数具有int*类型的形参,返回值类型是int。
      int (*func[5])(int *);
      func 右边是一个[]运算符,说明func是具有5个元素的数组;func的左边有一个*,说明func的元素是指针(注意这里的*不是修饰func,而是修饰 func[5]的,原因是[]运算符优先级比*高,func先跟[]结合)。跳出这个括号,看右边,又遇到圆括号,说明func数组的元素是函数类型的指 针,它指向的函数具有int*类型的形参,返回值类型为int。
    也可以记住2个模式:
    type (*)(....)函数指针
    type (*)[]数组指针
    在编程实践中,尤其是看别人代码的时候,常常会遇到比较复杂的变量声明,使用typedef作简化自有其价值,比如:
    下面是三个变量的声明,我想使用typdef分别给它们定义一个别名,请问该如何做?
    1 int *(*a[5])(int, char*);
    2 void (*b[10]) (void (*)());
    3 doube(* (*pa)[9])();
    答案与分析:
    对复杂变量建立一个类型别名的方法很简单,你只要在传统的变量声明表达式里用类型名替代变量名,然后把关键字typedef加在该语句的开头就行了。
    1 int *(*a[5])(int, char*);
    //pFun是我们建的一个类型别名
    typedef int *(*pFun)(int, char*);
    //使用定义的新类型来声明对象,等价于int* (*a[5])(int, char*);
    pFun a[5];
     
    1 void (*b[10]) (void (*)());
    //首先为上面表达式蓝色部分声明一个新类型
    typedef void (*pFunParam)();
    //整体声明一个新类型
    typedef void (*pFun)(pFunParam);
    //使用定义的新类型来声明对象,等价于void (*b[10]) (void (*)());
    pFun b[10];
     
    1 double(*[1]  (*pa)[9])()[2]  ;
    //首先为上面表达式蓝色部分声明一个新类型
    typedef double(*pFun)();
    //整体声明一个新类型
    typedef pFun (*pFunParam)[9];
    //使用定义的新类型来声明对象,等价于double(*(*pa)[9])();
    pFunParam pa;
    pa是一个指针,指针指向一个数组,这个数组有9个元素,每一个元素都是“doube(*)()”--也即一个指针,指向一个函数,函数参数为空,返回值是“double”。
  • 相关阅读:
    angularjs学习访问服务器(5)
    sublime text 3解放鼠标的快捷键总结
    AngularJS与服务器交互(4)
    android 串口调试
    QCom MSM MDP显示驱动一些点的简记
    如何提高android串口kernel log等级
    高通平台msm8909 LK 实现LCD 兼容
    MSM8909平台 LED背光的控制
    铝聚合物电池工作温度及低温电量差异的说明
    液晶屏工作稳定说明
  • 原文地址:https://www.cnblogs.com/fnlingnzb-learner/p/5987120.html
Copyright © 2011-2022 走看看