深度分析typedef--定义自己的数据类型
来源:互联网 发布:python 爬虫 慢 编辑:程序博客网 时间:2024/06/05 07:39
最近在看redis源码的时候看到Ae.h的时候看到如下源码:
/* Types and data structures */typedef void aeFileProc(struct aeEventLoop *eventLoop, int fd, void *clientData, int mask);typedef int aeTimeProc(struct aeEventLoop *eventLoop, long long id, void *clientData);typedef void aeEventFinalizerProc(struct aeEventLoop *eventLoop, void *clientData);typedef void aeBeforeSleepProc(struct aeEventLoop *eventLoop);
对于函数,typedef有两类自定义类型,恰好在Nginx和Redis中分别使用了一种风格。参见:函数指针--Nginx和Redis中两种回调函数写法
----以上选自《C语言编程:一本全面的C语言入门教程 (第3版)》
更深度的分析:
--以上出自《C语言入门经典(第四版)》
下面是一些常用的总结:
1、定义数组类型
typedef int myIntArray[100];
或
typedef int myIntArray [100];
则myIntArray a;
等价于
int a[100];
2、定义函数类型
typedef bool do();
则do就成为一种函数类型,它可以用来定义指向bool类型函数的指针,如下:
bool realDo();
do * doP = realDo; 或 do* doP = &realDo; (这两个语句是一样的,函数名本身就是一个指针,他们性质完全相同,只是哪个更容易理解一些而已)
还不明白的话,可以试运行以下的代码:
#include <iostream.h>
typedef bool a();
bool aaa()
{
cout << "ok" << endl;
return true;
}
void main()
{
a * aa = aaa;(此处 a * aa = &aaa; 也可以)
aa();
}
3、定义函数指针
typedef void (*funcPtr)(int);
上面的语句的意义是:定义了一个函数指针,它可以指向的函数类型是无反回值并且有一个int参数,如下:
#include <iostream.h>
typedef void (*funcPtr)(int);
void print(int a)
{
cout << a << endl;
}
void main()
{
funcPtr pFunc;
pFunc = print;
pFunc(1);
}
来个复杂的:
funcPtr aa(funcPtr bb);
如果不用typedef定义的函数类型,则要写成如下形式:
void (*aa(void (*bb) (int))(int);
就会很难懂。
4、定义指针
typedef int * intP;
也许新手用这个关键字不多,但它却是一个很有用的关键字,可以使代码模块化程度更好(即与其它代码的关联较少),在C++中还是实现Traits技术的基础,也是模板编程的基本语法之一。
若说变量定义是为变量命名,而typedef(或称为类型定义)就是为类型命名。既然都是命名,那就会有很多类似的地方。而变量定义我想大家都会使用,因此类型定义也必然会使用。
类型定义的语法可以归结为一句话:只要在变量定义前面加上typedef,就成了类型定义。这儿的原本应该是变量的东西,就成为了类型。
如,下面的变量定义:
int integer; //整型变量
int *pointer; //整型指针变量
int array [5]; //整型数组变量
int *p_array [5]; //整型指针的数组的变量
int (*array_pointer) [5];//整型数组的指针的变量
int function (int param);//函数定义,也可将函数名看作函数的变量
int *function (int param);//仍然是函数,但返回值是整型指针
int (*function) (int param);//现在就是指向函数的指针了
若要定义相应类型,即为类型来起名字,就是下面的形式:
typedef int integer_t; //整型类型
typedef int *pointer_t; //整型指针类型
typedef int array_t [5]; //整型数组类型
typedef int *p_array_t [5]; //整型指针的数组的类型
typedef int (*array_pointer_t) [5]; //整型数组的指针的类型
typedef int function_t (int param); //函数类型
typedef int *function_t (int param); //函数类型
typedef int (*function_t) (int param); //指向函数的指针的类型
注意,上面的函数类型在C中可能会出错,因为C中并没有函数类型,它的函数变量会自动退化成函数指针;在C++中好像是可以的。在这里主要说明的是形式上的相似性.
typedef的一般形式为:
typedef 类型 定义名;
在编程中使用typedef目的一般有两个,一个是给变量一个易记且意义明确的新名字,另一个是简化一些比较复杂的类型声明。
其实,在C语言中声明变量的时候,有个存储类型指示符(storage-class-specifier),它包括我们熟悉的extern、static、auto、register。在不指定存储类型指示符的时候,编译器会根据约定自动取缺省值。另外,存储类型指示符的位置也是任意的(但要求在变量名和指针*之前),也就是说以下几行代码是等价的:
static const int i;
const static int i;
int const static i;
const int static i;
根据C语言规范,在进行句法分析的时候,typedef和存储类型指示符是等价的!所以,我们把上述使用static的地方替换为typedef:
typedef const int i;
const typedef int i;
int const typedef i;
const int typedef i;
上述代码的语义是:将i定义为一个类型名,其等价的类型为const int。以后如果我们有i a代码,就等价于const int a。对于有指针的地方也是一样的,比如:
int const typedef *t;那么代码t p。就相当于int const *p。
另外,typedef不能和static等存储类型指示符同时使用,因为每个变量只能有一种存储类型,所以代码:typedef static int i;是非法的。
使用typedef简化复杂的变量声明
1)、定义一个有10个指针的数组,该指针指向一个函数,该函数有一个整形参数,并返回一个整型?
第一种方法:int (*a[10])(int);
第二种方法:typedef int (*pfunc)(int);
pfunc a[10];
2)、定义一个有10个指针的数组,该指针指向一个函数,该函数有一个函数指针(不带参数,返回值为空)参数,并返回空。
第一种方法:void (*a[10])(void (*)(void));
第二种方法:typedef void (*pfuncParam)(void);
typedef void (*pfunc)(pfuncParam);
pfunc a[10];
3)、一个指向有10个函数指针(不带参数,返回值为double)数组的指针
第一种方法:double (*)(void) (*p)[10];
第二种方法:typedef double (*pfunc)(void);
typedef pfunc (*pfuncParam)[10];
pfuncParam p;
总结:
typedef有两种用法:
一、一般形式,定义已有类型的别名
typedef 类型 定义名;
二、创建一个新的类型
typedef 返回值类型 新类型名(参数列表);
参考:
typedef用法详解
http://my.oschina.net/u/178323/blog/32452
typedef几种不常用用法 函数类型和函数指针
- 深度分析typedef--定义自己的数据类型
- typedef定义数据类型
- Windows自己定义的数据类型
- 用typedef定义类型的总结分析
- typedef定义函数类型分析
- 【C++笔记】宏定义数据类型与typedef
- 对象的定义和数据类型分析
- 一个typedef的定义
- typedef的定义说明
- 使用深度学习网络SSD识别自己定义的物体
- typedef定义的函数指针
- glibc之数据类型定义分析
- OpeCV中常用基本数据类型的定义分析之一
- OpeCV中常用基本数据类型的定义分析之二
- typedef定义
- 不熟悉数据类型的定义
- TI 数据类型的定义
- 数据类型的定义
- ssky-keygen + ssh-copy-id 无密码登陆远程LINUX主机
- windows xp下的NOTEPAD用最新x86插件转换的结果
- 程序,进程和线程的区别与联系
- 怎样让多个并发的线程暂停,然后在主线程中改变标记让它们继续运行
- 求a^b前n位和后n位
- 深度分析typedef--定义自己的数据类型
- HTML中的ul、li、ol、li、dl、dt、dd的区别讲解与示例
- PHP正则提取或替换img标记属性
- QT递归遍历目录
- npapi插件主动调用js函数的方法
- 修改Jar文件关联的方法 .
- 一些重要的算法
- asp.net遍历目录文件夹和子目录所有文件
- C#static关键字用法总结