1. typedef 最简单使用

[c-sharp] view plain copy

  1. typedef long byte_4; // 给已知数据类型long起个新名字,叫byte_4

你可以在任何需要 long 的上下文中使用 byte_4。注意 typedef 并不创建新的类型。它仅仅为现有类型添加一个同义字。

2. typedef 修饰数组

[cpp] view plain copy

  1. typedef char mySizes[100];
  2. mySizes xxx;
  3. typedef char [100] mySizes; //error

这里 mySize 就是一个大小为100的 char 数组,sizeof(mySize) 为 100。

3. typedef 修饰指针

[c-sharp] view plain copy

  1. typedef char * pstr;
  2. int mystrcmp(pstr, pstr);
  3. ......
  4. int mystrcmp(const pstr, const pstr); //error

这里有一个 typedef 陷阱。标准函数 strcmp()有两个‘const char *’类型的参数。因此,它可能会误导人们象上面这样声明。

按照顺序,‘const pstr’被解释为‘char * const’(一个指向 char 的常量指针),而不是‘const char *’(指向常量 char 的指针)。

其实这点很好理解,const 就是修饰 pstr 指针的,并不是简单替换。

这个问题很容易解决:

[c-sharp] view plain copy

  1. typedef const char * cpstr;
  2. int mystrcmp(cpstr, cpstr); // 现在是正确的

4. typedef 修饰结构体

[c-sharp] view plain copy

  1. typedef struct tagMyStruct   
  2. {
  3. int iNum;   
  4. long lLength;   
  5. } MyStruct;

这语句实际上完成两个操作:
(1).定义一个新的结构类型

[c-sharp] view plain copy

  1. struct tagMyStruct   
  2. {   
  3. int iNum;   
  4. long lLength;   
  5. };   

分析:

tagMyStruct ,实际上是一个临时名字,struct 关键字和 tagMyStruct一起,构成了这个结构类型,不论是否有typedef,这个结构都存在。

我们可以用 struct tagMyStruct xxName 来定义变量,但要注意,使用tagMyStruct xxxrName 来定义变量是不对的,因为struct 和tagMyStruct合在一起才能表示一个结构类型。

(2). typedef 为这个新的结构起了一个名字,叫 MyStruct。

typedef struct tagMyStruct MyStruct;因此,MyStruct实际上相当于struct  tagMyStruct,我们可以使用MyStruct varName来定义变量。

5. typedef & 结构的问题

在结构中包含指向它自己的指针

[c-sharp] view plain copy

  1. typedef struct tagNode   
  2. {   
  3. char *pItem;   
  4. pNode pNext; // error  
  5. } *pNode;

答案与分析: 
    根据我们上面的阐述可以知道:要知道pNode表示的是类型的新名字,那么在类型本身还没有建立完成的时候,这个类型的新名字 pNoed 也还不存在,也就是说这个时候编译器根本不认识pNode。

解决这个问题的方法有多种:

[cpp] view plain copy

  1. // 1)
  2. typedef struct tagNode   
  3. {
  4. char *pItem;
  5. struct tagNode *pNext;   
  6. } *pNode;   
  7. // 2)   
  8. typedef struct tagNode* pNode;   
  9. struct tagNode   
  10. {
  11. char *pItem;
  12. pNode pNext;
  13. };
  14. //注意:在这个例子中,你用 typedef 给一个还未完全声明的类型起新名字。C语言编译器支持这种做法。
  15. // 3)规范做法:   
  16. struct tagNode   
  17. {
  18. char *pItem;
  19. struct tagNode *pNext;   
  20. };
  21. typedef struct tagNode *pNode;

6. typedef 与 #define的问题
有下面两种定义pStr数据类型的方法,两者有什么不同?哪一种更好一点?

[c-sharp] view plain copy

  1. typedef char* pStr;   
  2. #define pStr char*;   

答案与分析:

通常讲,typedef要比#define要好,特别是在有指针的场合。
请看例子:

[c-sharp] view plain copy

  1. typedef char* pStr1;
  2. #define pStr2 char *
  3. pStr1 s1, s2; // char* s1; char* s2; 
  4. pStr2 s3, s4; // char* s3, s4;即 char s4;

在上述的变量定义中,s4则定义成了char,不是我们所预期的指针变量,根本原因就在于#define只是简单的字符串替换而typedef则是为一个类型起新名字。

上例中define语句必须写成 pStr2 s3, *s4; 这这样才能正常执行。

7. typedef 与 复杂的变量声明

在编程实践中,尤其是看别人代码的时候,常常会遇到比较复杂的变量声明,使用typedef作简化自有其价值,比如:   
下面是三个变量的声明,我想使用typdef分别给它们定义一个别名,请问该如何做?

[cpp] view plain copy

  1. int *(*a[5])(intchar*);
  2. void (*b[10]) (void (*)());
  3. double(*)() (*pa)[9];

答案与分析:

对复杂变量建立一个类型别名的方法很简单,你只要在传统的变量声明表达式里用类型名替代变量名,然后把关键字typedef加在该语句的开头就行了。

8. typedef 修饰函数指针

[cpp] view plain copy

  1. //1. 定义一个函数指针
  2. typedef int(_cdecl *FUN_Start)(UCHAR);
  3. /* typedef的功能是定义新的类型。定义这种类型为指向某种函数的指针,这函数以一个UCHAO为参数并返回int类型。*/
  4. //2. 定义这个函数指针的一个变量
  5. FUN_Start fun_Start;
  6. //3. 把函数的地址赋给此函数指针
  7. fun_Start = (FUN_Start)GetProcAddress(m_hLibrary,"Rec_SetDevice");
  8. //4. 调用
  9. if (fun_Start('a') == 1) //直接通过函数指针调用
  10. {......}
  11. //当然也可以这样
  12. if ( (*)fun_Start('a') == 1) //先用*fun_start取出它所指的函数类型,再调用
  13. {......}

因为函数名就是一个地址,该函数名所代表的函数的入口地址。

注:

总之一点,不要把typedef看成简单的替换,要看成一种新的命名,要与default相区别!!

c/c++中typedef详解(此文对typedef用于结构体的定义说明得很清楚到位)相关推荐

  1. 浏览器中location详解

    浏览器中location详解 window.location对象用于获取当前页面的URL信息. 属性解析 1. href 当前页面的URL. 比如访问github.com,在控制台中输入locatio ...

  2. Rust中结构体的定义和实例化

    文章目录 使用字段初始化简写语法 使用结构体更新语法从其他实例创建实例 使用没有命名字段的元组结构体来创建不同的类型 没有任何字段的类单元结构体 结构体和我们在"元组类型"部分论过 ...

  3. 函数中{}输出格式详解(C#)

    Console.WriteLine()函数中{}输出格式详解(C#) Console.WriteLine()函数的格式一直没怎么注意.今天同事问起Console.WriteLine({0:D3},a) ...

  4. Java中CAS详解

    转载自  Java中CAS详解 在JDK 5之前Java语言是靠synchronized关键字保证同步的,这会导致有锁 锁机制存在以下问题: (1)在多线程竞争下,加锁.释放锁会导致比较多的上下文切换 ...

  5. 【转】图形流水线中坐标变换详解:模型矩阵、视角矩阵、投影矩阵

    转自:图形流水线中坐标变换详解:模型矩阵.视角矩阵.投影矩阵_sherlockreal的博客-CSDN博客_视角矩阵 图形流水线中坐标变换详解:模型矩阵.视角矩阵.投影矩阵 图形流水线中坐标变换过程 ...

  6. oracle itl解析,oracle数据块dump文件中ITL详解

    oracle数据块dump文件中ITL详解 dump出Oracle block后,可以看到事物槽,包含有事物槽号(ITL),XID,UBA,FLAG,LCK,SCN. 本文主要讨论FLAG标记的规则, ...

  7. android中getSystemService详解

    原文地址:android中getSystemService详解作者:邹斌 http://blog.sina.com.cn/s/blog_71d1e4fc0100o8qr.html http://blo ...

  8. Oracle中CONCAT详解

    Oracle中CONCAT详解 1.什么是CONCAT 新的改变 我们对Markdown编辑器进行了一些功能拓展与语法支持,除了标准的Markdown编辑器功能,我们增加了如下几点新功能,帮助你用它写 ...

  9. Java中LinkedList详解

    Java中LinkedList详解 LinkedList底层是双向链表 单向链表 双向链表 LinkedList新增的方法 主要增加了针对头结点与尾结点进行操作的方法, 即针对第一个元素和最后一个元素 ...

最新文章

  1. 2022-2028年中国新能源环卫车行业深度调研与投资战略规划分析报告
  2. HANA 数据库备份hang住的解决办法
  3. ClassNotFoundException和NoClassDefFoundError的区别
  4. Android中自定义xmlns
  5. 访问量大如何增加服务器,服务器流量过大原因及解决方法
  6. 使用多线程的方式调用chineseocr_API
  7. af_netlink_2、netlink简介
  8. 无人驾驶泊车?你要再多等等,百度Apollo和大众刚启动合作
  9. php redis 事务应用,redis事务有什么用
  10. 2020德勤面试开始了吗_曝!玛氏、德勤、携程面试题新鲜出炉!2020第一波面试复盘来了......
  11. 案例|工业物联网解决方案•空调系统智能监控运维云平台
  12. 关于Visual Studio 2019安装时VS installer无法下载文件,进度条为0,显示网络有问题的解决办法
  13. JS 之 图片编辑器插件
  14. mmall 项目实战(一)项目初始化
  15. 一步控制台编译java_在控制台运行一个 Java 程序 Test . class ,使用的命令正确的是( )_学小易找答案...
  16. webuploader怎样上传文件夹
  17. 整理一些前端模版比较好的网站
  18. 出现无法解析的外部符号 LZ4_decompress_safe等问题
  19. RFID标签的编码标准
  20. 学习下什么是微服务架构/平台

热门文章

  1. 普通人也要学python吗-普通人学Python有意义吗?
  2. python使用什么格式划分语句块-python以什么划分语句块
  3. 不属于python开发用户界面第三方库的是-模拟试卷C【单项选择题】
  4. python编程有什么用处-python中的生成器是什么?生成器有什么用处?
  5. php和python对比-python学习笔记一和PHP的一些对比
  6. python3.8安装pip-MAC本安装python3.8后,pip3命令无法更新问题
  7. python入门到精通需要学多久-python学习从入门到精通要多久
  8. python下载的库要放到哪里-Python下载url并保存文件的三种方法
  9. python json.loads()中文问题-python处理json数据中的中文
  10. mybatis之ResultMap