admin 管理员组文章数量: 887053
2024年1月23日发(作者:mybatisplus wrapper)
C语言typedef用法总结
黄海涛,2012-3-11
C语言中的typedef可以让人感觉很清新,但也可以让人感觉神秘。当你一层层剥开它的时候,神秘的面纱终会摘下……
让我们一起来探究其中的秘密吧!
一、概述
1、 类型定义符typedef
C语言提供了一个称为typedef的工具,它允许你为各种数据类型定义新的名字。
定义形式:
typedef 原类型名 新类型名;
它的格式与变量声明完全一样,只是把typedef这个关键字放在声明的前面,但typedef并不创建变量,而是为指定类型引入一个新的名字。
2、 实质
其实质是:为现有类型取个新名字,它并没有引入新的类型。
typedef是一种声明形式,它为一种类型引入新的名字,而不是产生新的类型,也不会为变量分配空间。
3、 作用时机
在某些方面,typedef类似于宏文本替换,但typedef是类型定义符,在编译时会有相应类型的检查。typedef是由编译器解释的。
▲typedef与#define的区别
A.#define后面没有分号,而typedef后面有分号;
B.#define不是关键字,而typedef是关键字;
C.宏定义中宏名紧跟着#define,而typedef中的类型名并不紧接其后;
D.可以用其他类型说明符对宏名进行扩展,但对typedef定义的类型名却不行;例如:
#define INT_TYPE int
unsigned INT_TYPE i; /*没有问题*/
typedef int INT_TYPE;
unsigned INT_TYPE i; /*错误!非法*/
E.在连续几个变量声明中,typedef定义的类型名可以保证声明中所有的变量均为同一种类型,而#define定义的宏名则无法保证。
4、 使用原因
1)表达方式更简洁,简化编程;
2)使程序参数化,提高程序的可移植性;
3)为程序提供更好的说明性,可以引入一个易记且意义明确的新名字,提升可维护性。
5、 缺点
允许一些看上去混乱的语法,可以把几个声明放在一个声明中。如:
typedef int *ptr, (fun)(), arr[5]; //语法没有问题
/* ptr是“指向int的指针”类型
* fun是“指向返回值为int的函数的指针”类型
* arr是“长度为5的int型数组”类型
*/
const unsigned long typedef int volatile *ptr;
/* typedef可以嵌入到声明的中间部分*/
二、使用typedef声明定义时的限制
1、 原类型可以带有类型限定符
typedef const int CINT /*原类型中含有const类型限定符*/
2、 原类型可以是typedef声明的新类型名
typedef unsigned char CK_BYTE;
typedef CK_BYTE CK_CHAR;
3、 原类型不可带有存储类别
typedef static int SINT; /*错误,指定的存储类不能多于1个*/
typedef register int RIN;
存储类关键字:auto、extern、register、static与typedef
但在存储类说明符中,typedef是个例外,它不会真正影响对象的存储特性。其他存储类说明符确定所声明对象的生存期。
三、typedef基本数据类型
typedef的一个重要用途就是声明定义机器无关的类型名,提高程序的可移植性。
像操作硬件设备等使用长度明确的数据,对应的类型长度也应该明确。在32位机器上可以如下声明定义:
typedef signed char
typedef unsigned char
typedef signed short
typedef unsigned short
typedef signed int
typedef unsigned int
S8;
U8;
S16;
U16;
S32;
U32;
带符号的可能用到的比较少。
你也可能如下声明定义:
typedef unsigned char
typedef unsigned short
typedef unsigned int
typedef void
BYTE;
WORD;
DWORD;
VOID;
*BYTE_PTR;
*WORD_PTR;
*DWORD_PTR;
*VOID_PTR;
相对应的指针:
typedef unsigned char
typedef unsigned short
typedef unsigned int
typedef void
如果要将程序移植到另一个平台,程序中使用的是typedef的新类型名,那么移植时修改typedef中相应信息即可。
四、typedef构造类型
C语言中的构造类型主要包括:数组类型、结构体类型与共用体类型。
1、数组类型
typedef int ARRAY[10];
当你想定义多个同样大小的数组时,直接用新类型名定义即可。如:
ARRAY a, b;
2、结构体类型
struct tagMyStruct
{
int num;
long lLength;
};
struct tagMyStruct a; /*声明定义结构体变量*/
typedef struct tagMyStruct MyStruct; /*为该结构体引入一个新类型名*/
MyStruct a; /*与struct tagMyStruct a;等效*/
tagMyStruct b; /*却不行,它只是一个标签而已*/
整体声明定义:
typedef struct tagMyStruct
{
int num;
long lLength;
}MyStruct; /* MyStruct是该结构引入的新类型名*/
struct tagMyStruct val; /*使用结构标签tagMyStruct*/
MyStruct val; /*使用结构新类型名MyStruct*/
/*请区别以下写法:*/
struct tagMyStruct
{
int num;
long lLength;
}MyStruct; /* 此处的MyStruct是该结构声明的变量*/
MyStruct val; /*错误*/
结构体中的问题:
typedef struct tagNode
{
int data;
pNode pNext; /*错误,pNode类型名还不存在*/
} *pNode;
C语言允许在结构体中包含指向它自己的指针,在建立链表等数据结构时可以看到大量这样的例子。解决办法有多种:
1)
typedef struct tagNode
{
/*a与b都是拥有10个int型数据的数组*/
int data;
struct tagNode *pNext;
} *pNode;
2)
/*使用前面已知的标签*/
typedef struct tagNode *pNode; /*支持给未声明的类型引入新名字*/
struct tagNode
{
int data;
pNode pNext;
};
3)规范的写法
struct tagNode
{
int data;
struct tagNode *pNext;
};
typedef struct tagNode *pNode;
五、typedef指针类型
1、 简单使用
typedef char *pStr;
pStr1 s1, s2; /*s1与s2均被声明为char类型指针*/
使用const类型限定符带来的困惑:
typedef char * pStr;
char string[4] = "abc";
/*const限定的是char,即指针p1所指的内容不能修改,但p1可以改变*/
const char *p1 = string;
char const *p1 = string; /*const位于类型说明符前后等价*/
p1++; /*可以正确执行*/
/*const限定的是(char *),即指针p1所指的内容可以修改,但p1不能变化*/
char *const p1 = string;
p1++; /*错误,不能执行这个操作*/
/*const限定的是pStr,也就是(char *),因为pStr是一个整体,即指针p2所指的内容可以修改,但p2不能变化。编译器认为pStr跟普通数据类型没有什么区别,它只是我们自己引入的一个新类型名而已*/
const pStr p2 = string;
p2++; /*错误,不能执行这个操作*/
/*const限定的也是pStr,即指针p2所指的内容可以修改,但p2不能变化*/
pStr const p2 = string;
p2++; /*错误,不能执行这个操作*/
解决办法:在typedef时指明const类型限定符
typedef const char *pcStr;
pcStr p2 = string;
p2++; /*可以正确执行*/
2、 函数指针
typedef int (*PFUN)(char *, char *);
/*为函数指针引入了一个新类型名PFUN,是“一个指向函数的指针,该函数具有两个char *型参数,返回值类型为int”*/
PFUN strcmp, numcmp; /*都是指向函数的指针*/
3、 函数指针与数组
/*a为函数指针,该函数有一个int型参数,且返回值类型为int*/
int (*a)(int);
/*a为有10个函数指针的数组,该函数有一个int型参数,且返回值类型为int*/
int (*a[10])(int);
typedef int (*PFUN)(int);
PFUN a[10];
/*在使用typedef引入新类型名PFUN后,我们看到了熟悉的普通数组声明方式*/
4、 复杂的声明
/*下面的这个声明让人望而生畏,很难弄清楚是做什么用的*/
int (*Register(int (*pf)(const char *, const char *)))(const char
*, const char *);
/*我们将它的构成解剖,然后使用typedef*/
/*它由两大部分构成*/
int (*pf)(const char *, const char *) ①
int (*Register( ① ))(const char *, const char *); ②
/*第一部分看到有些眼熟了吧?*/
typedef int (*PFUN)(const char *, const char *);
PFUN Register(PFUN pf);
有人可能会问,会有程序员写这样的代码吗?它有什么用呢?典型的例子是signal()原型的声明,signal()是一个系统调用,用于通知运行时系统,当某种特定的“软件中断”发生时调用特定的程序。你可以通过参数传递告诉它中断的类型以及用于处理中断的程序。在ANSI C标准中,signal()的声明如下:
void (*signal(int sig, void (*func)(int)))(int);
/*我们使用上面同样的方式解剖它,然后使用typedef*/
/*它由两大部分构成*/
void (*func)(int) ①
void (*signal(int sig, ①))(int); ②
/*跟上面的例子同样的简洁吧?*/
typedef void (*ptr_to_func)(int);
ptr_to_func signal(int sig, ptr_to_func);
由于水平有限,文中肯定存在很多不足之处,恳请阅读者批评指正,相互交流,学习提高。
六、参考资料
1、《C程序设计》(第三版):谭浩强著,清华大学出版社2005.07
2、《C程序设计语言(The C Programming Language)》(第2版中英文版):(美)Brian
han,Dennis e著,徐宝文 李志译,机械工业出版社2004 年1月
3、《C专家编程(Expert C Programming)》(中英文版):(美)林登(LinDen,P.V.D)著,徐波译,人民邮电出版社2002.12
4、《C陷阱与缺陷(C Traps And Pitfalls)》(中英文版):(美)Andrew Koenig著,高巍译,人民邮电出版社2003
5、《C语言深度解剖》陈正冲著,北京航空航天大学出版社2010
6、《C语言参考手册(C:A Reference Manual)》(第五版):(美)Samuel on III,Guy
Jr.著,邱仲潘等译,机械工业出版社2003 年8月
7、《想成为嵌入式程序员应知道的0x10个基本问题.doc》作者:Jones Nigel
版权声明:本文标题:C语言typedef用法总结 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.freenas.com.cn/jishu/1705961356h495807.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论