在学习Redis中的dict.h文件中,遇到了如下的语句:typedef void (dictScanFunction)(void *privdata, const dictEntry *de);对此我感到十分困惑,找了关于typedef和函数指针的相关资料,现总结如下:
一、typedef的用法:
typedef 类型名称 类型标识符
二、typedef主要应用的几种形式:
1.为基本数据类型定义新的类型名
typedef unsigned int COUNT;
2.为自定义数据类型(结构体、公用体和枚举类型)定义简洁的类型名称:
在C语言中,struct Point{}结构体后,定义新的变量一定得 struct Point oPoint1;而如果用的是 typedef struct Point则在后面定义时不用加struct。
看下面的程序:
1.
#include<stdio.h>
int main() {
struct Point//定义了一个结构体
{
double x;
double y;
double z;
};
struct Point oPoint1 = { 100,100,0 };
printf("%f", oPoint1.y);
while (1);
return 0;
}
2.
#include<stdio.h>
int main() {
typedef struct
{
double x;
double y;
double z;
}Point;
Point oPoint1 = { 100,100,0 };//Point是一个结构体类型,不用加struct
printf("%f", oPoint1.y);
while (1);
return 0;
}
在c++中如果用typedef的话,又会造成区别:
#include<iostream>
using namespace std;
int main() {
struct Student1
{
int a;
}stu1;//stu1是一个变量
stu1.a = 2;
cout << stu1.a << endl;
typedef struct Student2
{
int a;
}stu2;//stu2是一个结构体类型
stu2 stu3;
stu3.a = 2;
cout << stu3.a << endl;
while (1);
return 0;
}
定义结构变量的一般格式为:struct 结构名
{
类型 变量名;
类型 变量名;
...
} 结构变量;
结构名是结构的标识符不是变量名。
另一种常用格式为:
typedef struct 结构名
{
类型 变量名;
类型 变量名;
...
} 结构别名;
3.为数组定义简洁的类型名称:
在C语言中,可以将长度为10的整型数组看作为一个新的数据类型,再利用typedef为其重定义一个新的名称,可以更加简洁形式定义此种类型的变量,具体的处理方式如下:
typedef int INT_ARRAY_10[10];
typedef int INT_ARRAY_20[20];
INT_ARRAY_10 a,b,c,d;
INT_ARRAY_20 e;
其中INT_ARRAY_10和INT_ARRAY_20为新的类型名,10 和20 为数组的长度。a,b,c,d均是长度为10的整型数组,e是长度为20的整型数组。
4.为指针定义简洁的名称
(1)为数据指针定义新的名称
#include<iostream>
using namespace std;
int main() {
typedef char* STRING;
STRING csName = { "Jhon" };
for (int i = 0;i < 5;i++)
cout << csName[i] << " ";
cout << endl;
while (1);
return 0;
}
(2)可以为函数指针定义新的名称
在文章后面详细解释
三、tpedef与#define的区别
1.#define AREA double 与typedef double AREA 可以达到相同的效果。但是其实质不同,#define为预编译处理命令,主要定义常量,此常量可以为任何的字符及其组合,在编译之前,将此常量出现的所有位置,用其代表的字符或字符组合无条件的替换,然后进行编译。typedef是为已知数据类型增加一个新名称,其原理与使用intdouble等保留字一致。
2.#define 不是语句 不要在行末加分号,否则会连分号一块置换
3.举例:
#define int_ptr int*
int_ptr a, b; //相当于int * a, b; 只是简单的宏替换
typedef int*int_ptr;
int_ptr a, b; //a,b 都为指向int的指针,typedef为int* 引入了一个新的助记符
函数指针的学习
这部分主要是通过例子来学习的。
1.首先学习一下如何理解复杂的申明:准则是从变量名开始,先右后左
int (*func)(int *p);
找到变量名 func,左边有*,说明func是一个指针,然后跳出括号,右边又是括号,说明(*func)是函数。func是一个指向函数的指针,左边int说明该函数的返回类型是int;
int(*func[5])(int*);
func右边是一个[]运算符,说明func是具有5个元素的数组,func左边有一个*,说明func的元素是指针,跳出括号,右边,说明func数组的元素是函数类型的指针,指向的函数具有int*类型的形参,返回类型是int;
2.先看下面的例子:
#include<stdio.h> #include<assert.h> typedef int(*FP_CALC)(int, int);//FP_CALC是一个函数指针,指向的函数;类型是 int(函数名)( ) int add(int a, int b)
{return a + b;}int sub(int a, int b){return a - b;}int mul(int a, int b){return a * b;}int div(int a, int b){return b ? a / b : -1;}//定义一个函数,参数为op,返回一个指针。该指针类型为 拥有两个int参数、//返回类型为int 的函数指针。它的作用是根据操作符返回相应函数的地址FP_CALC calc_func(char op){switch (op){case '+': return add;//返回函数的地址case '-': return sub;case '*': return mul;case '/': return div;default:return NULL;}return NULL;}//从变量名出发,先右后左,s_calc_func是变量,右边是(char op),说明s_calc_func是函数,它的参数是 op,//左边是一个指针,int(* )(int,int);说明返回的类型是一个函数指针int(*s_calc_func(char op)) (int, int){return calc_func(op);}//最终用户直接调用的函数,该函数接收两个int整数,和一个算术运算符,返回两数的运算结果int calc(int a, int b, char op){FP_CALC fp = calc_func(op); //根据预算符得到各种运算的函数的地址int(*s_fp)(int, int) = s_calc_func(op);//用于测试assert(fp == s_fp); // 可以断言这俩是相等的if (fp) return fp(a, b);//根据上一步得到的函数的地址调用相应函数,并返回结果else return -1;}void main(){int a = 100, b = 20;printf("calc(%d, %d, %c) = %d\n", a, b, '+', calc(a, b, '+'));printf("calc(%d, %d, %c) = %d\n", a, b, '-', calc(a, b, '-'));printf("calc(%d, %d, %c) = %d\n", a, b, '*', calc(a, b, '*'));printf("calc(%d, %d, %c) = %d\n", a, b, '/', calc(a, b, '/'));while (1);} 3.回到最初的问题上,理解typedef void (dictScanFunction)(void *privdata, const dictEntry *de);的表达。定义的不是函数指针,而是一种函数类型,可以利用 dictScanFunction完成类似函数指针的用法,看下面的例子://注意这里不是函数声明而是函数定义,它是一个地址,你可以直接输出add看看
#include<iostream> using namespace std; void PrintWord(int n) { cout << n << endl; } int main() { //1 typedef void (func1)(int);//不是函数指针,定义了一个函数类型 func1 *myfunc1;//定义函数指针 myfunc1 = PrintWord; myfunc1(5); //2 typedef void(*func2)(int);//定义了一种类型,2和3的区别在于typedef的作用上 func2 myfunc2;//实例化 myfunc2 = PrintWord; myfunc2(5); //3 void(*func3)(int); func3 = PrintWord; func3(5); while (1); return 0; }
typedef void (FT)(int,int); 申明的函数类型如何使用呢?
首先可以用来申明函数:
FT x,y等价于:
void x(int,int);
void y(int,int);
#include <stdio.h> typedef void (FT)(int*, int*); FT x, y, *z, u; //void x(int*,int*) //void y(int*,int*) //void *z(int*,int*) //void u(int*,int*) int main() { int a = 1, b = 2; x(&a, &b); (*y)(&a, &b);//y(&a,&b)也可以; z = x;//这里x是一个函数名,但是编译器会把函数名转换为函数指针变量,所以也可以显式写成z = &x; z(&a, &b); //u = x;//这里出错了这里u是一个函数名称,是一个指针常量,类似于数组名称,是不能够被赋值的 while (1); return 0; } void x(int* a, int*b) { *a = *a + *b; printf("%d\n", *a); } void y(int*a, int* b) { *a = *a * (*b); printf("%d\n", *a); }
4.在网上找到这篇blog,比较好,记录下来:
http://blog.csdn.net/sruru/article/details/7916296