[C++][基础概念](四)typedef的学习

     在学习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)
//注意这里不是函数声明而是函数定义,它是一个地址,你可以直接输出add看看
{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完成类似函数指针的用法,看下面的例子:

#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


  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值