zoukankan      html  css  js  c++  java
  • 理解typedef(转)

    // 从别人那转的,调整下格式便于阅读。

    首先请看看下面这两句:

    typedef int a[10];
    
    typedef void (*p)(void); 

    如果你能一眼就看出它们的意思,那请不要再往下看了。如果你不太理解,或概念还有些模糊,请继续往下看吧。

    typedef用来声明一个别名,typedef后面的语法,是一个声明。本来这里不会产生什么误解的,但结果却出乎意料,产生误解的人不在少数。罪魁祸首又是那些害人的教材。在这些教材中介绍typedef的时候通常会写出如下形式:

    typedef int PARA;

    这种形式跟#define int PARA几乎一样!这些教材的宗旨是由浅入深,但实际做出来的行为却是以偏盖全!

    的确,这种形式在所有形式中是最简单的,但却没有对 typedef进一步解释,使得不少人用#define的思维来看待typedef,把int与PARA分开来看,int是一部分,PARA是另一部分,但实际上根本就不是这么一回事。int与PARA是一个整体!就象int i:声明一样是一个整体声明,只不过int i定义了一个变量,而typedef定义了一个别名。

    由于持有这种错误的观念,就会无法理解如下一些声明:

    typedef int a[10];               
    typedef void (*p)(void);

    会以为a[10]是int的别名,(*p)(void)是void的别名,但这样的别名看起来又似乎不是合法的名字,于是陷入困惑之中。实际上,上面的语句把a声明为具有10个int元素的数组的类型别名,p是一种函数指针的类型别名。

    虽然在功能上,typedef可以看作一个跟int PARA分离的动作,但语法上typedef属于存储类声明说明符,因此严格来说,typedef int PARA整个是一个完整的声明。

    定义一个函数指针类型。比如原函数是:

    void func(void);

    那么定义的函数指针类型就是:

    typedef void (*Fun)(void);

    然后用此类型生成一个指向函数的指针:

    Fun func1;

    当func1获取函数地址之后,那么你就可以向调用原函数那样来使用这个函数指针:func1(void);

    下面是理解typedef的正确方法,分为以下几步:

    1. 确定被声明的类型:遇到typedef时,从左到右进行扫描,找到第一个“陌生”的标志符,这个标志符就应该是语句所声明的类型名称。例如: typedef int* (* pt)(int* (*pn)(int * p1,int *p2),int * p3); 如果pt是生词(既不是保留字,也不是生命过的类型),那么它就是要声明的类型。其它的名字都是为了阅读方便的占位符,可有可无。也就是说,上面的语句等价为: typedef int * (*pt)(int * (*)(int *, int *),int *);

    2. 之后一旦遇到该类型声明的变量,则在该类型的typedef式中用变量代替类型,去掉typedef关键字,所得到的声明式等价与原来的声明。例如: pt p; 这个声明式,可以经过两步变化为等价的声明式。

    首先,回到pt的typedef式: typedef int * (*pt)(int * (*)(int *, int *),int *); 用p代替pt: typedef int * (*p)(int * (*)(int *, int *),int *); 然后把typedef去掉,得到: int * (*p)(int * (*)(int *, int *),int *); 这个语句与 pt p;意义相同。

    如果基础扎实,应该知道,这是个函数指针的声明,所指向的函数有两个int * 参数,返回一个int *值,第二个参数是int * ,整个函数返回一个int *。

    typedef和define的区别

    typedef和define都可以用来给对象取一个别名,但是两者却有着很大不同。

    1. 首先,二者执行时间不同 关键字typedef在编译阶段有效,由于是在编译阶段,因此typedef有类型检查的功能。 Define则是宏定义,发生在预处理阶段,也就是编译之前,它只进行简单而机械的字符串替换,而不进行任何检查。
    #define用法例子:

    #define f(x) x*x       
    main( )       
    {           
    int a=6,b=2,c;           
    c=f(a) / f(b);           
    printf("%d //n",c);       
    } 

    程序的输出结果是: 36,根本原因就在于#define只是简单的字符串替换。


    2. 功能不同 Typedef用来定义类型的别名,这些类型不只包含内部类型(int,char等),还包括自定义类型(如struct),可以起到使类型易于记忆的功能。 如:

    typedef int (*PF) (const char *, const char *); 

    定义一个指向函数的指针的数据类型PF,其中函数返回值为int,参数为const char *。


    typedef 有另外一个重要的用途,那就是定义机器无关的类型,例如,你可以定义一个叫 REAL 的浮点类型,在目标机器上它可以i获得最高的精度:

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

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

    typedef float REAL;
    #define不只是可以为类型取别名,还可以定义常量、变量、编译开关等。
    3. 作用域不同 #define没有作用域的限制,只要是之前预定义过的宏,在以后的程序中都可以使用。 而typedef有自己的作用域。

    void fun()          
    {              
    #define  A  int          
    }           
    void   gun()       
    {       
    //在这里也可以使用A,因为宏替换没有作用域,        
    //但如果上面用的是typedef,那这里就不能用A ,不过一般不在函数内使typedef     
    }

    4. 对指针的操作 二者修饰指针类型时,作用不同。

    typedef int *pint;        
    #define PINT int *
           
    const pint p;//p不可更改,p指向的内容可以更改,相当于int * const p;
    const PINT p;//p可以更改,p指向的内容不能更改,相当于 const int *p; 或 int const *p;
    
           
    pint s1, s2;  //s1和s2都是int型指针        
    PINT s3, s4;  //相当于int * s3,s4;只有一个是指针
  • 相关阅读:
    Dynamics AX 2012 R2 配置E-Mail模板
    Dynamics AX 2012 R2 设置E-Mail
    Dynamics AX 2012 R2 为运行失败的批处理任务设置预警
    Dynamics AX 2012 R2 耗尽用户
    Dynamics AX 2012 R2 创建一个专用的批处理服务器
    Dynamics AX 2012 R2 创建一个带有负载均衡的服务器集群
    Dynamics AX 2012 R2 安装额外的AOS
    Dynamics AX 2012 R2 将系统用户账号连接到工作人员记录
    Dynamics AX 2012 R2 从代码中调用SSRS Report
    Dynamics AX 2012 R2 IIS WebSite Unauthorized 401
  • 原文地址:https://www.cnblogs.com/tangdoudou/p/3198384.html
Copyright © 2011-2022 走看看