typedef用法,函数指针

本文详细介绍了函数指针的声明方法,包括int(*a)(int,int)和typedef重定义的使用。重点讲解了如何用函数指针作为函数返回值,并演示了typedef在不同类型声明中的应用,如函数指针别名和数组别名。此外,还讨论了typedef在C语言中的常见用法和陷阱。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

函数指针的声明

  1. 函数指针的声明
int (*a)(int,int)=NULL;
  1. typedef重定义
typedef int (*PF)(int,int);//函数指针别名
PF a=NULL;
typedef int (*PFS[4])(int,int);//函数指针别名
PFS b={NULL};//定义了一个函数指针数组,4个长度

例程

typedef int (*PF)(int,int);//函数指针别名
typedef int (*PFS[4])(int, int);//函数指针数组别名
int add(int a, int b) {//两个数相加
	return a + b;
}

int subtract(int a, int b) {//两个数相减
	return a - b;
}
int multiply(int a, int b) {//两个数相乘
	return a * b;
}
int divide(int a, int b) {//两个数相除
	return a / b;//会丢失精度
}
//返回函数指针
PF judge(char buff) {//判断运算符进而选择适合的函数
	switch (buff)
	{
	case '+':return add;
	case '-':return subtract;
	case '*':return multiply;
	case '/':return divide;
	default :return NULL;
		break;
	}
}

int main()
{

	char c = 0;
	int a = 0;
	int b = 0;
	int (*function)(int, int)=NULL;//函数指针
	PFS b = { NULL };
	int x;
	printf("请输入表达式:\n");
	x=scanf_s("%d%c%d", &a,&c,1,&b);
	function = judge(c);
	if (function != NULL) {	//判断指针是否合法
		printf("表达式%d %c %d = %d\n", a, c, b, function(a, b));
	}else printf("表达式输入错误\n");
}

1.函数声明-1

int (*function)(int, int)=NULL;//函数指针
//函数指针类型	函数名字相当于(*function)	返回函数指针的输入参数类型
//			也就相当于函数声明时的名字和参数部分
//int 			(*ff(int a,int b))			(int ,int) {
int (*ff(int a,int b))(int ,int) {
	printf("a+b=%d\n", a + b);
	return add;
}

2.函数声明-2

//利用typedef起别名
typedef int (*PF)(int,int);//函数指针别名
PF ff(int a ,int b) {
	printf("a+b=%d\n", a + b);
	return add;
}

3.使用

int main(){
	int a = 2;
	int b = 5;
	printf("%d+%d=%d\n", a, b, ff(a,b)(a,b));
	return 0;
}	

输出:
在这里插入图片描述

用函数指针作为函数的返回值

  1. 指针函数的定义

    顾名思义,指针函数即返回指针的函数。其一般定义形式如下:

    类型名 *函数名(函数参数表列);
    

    其中,后缀运算符括号“()”表示这是一个函数,其前缀运算符星号“*”表示此函数为指针型函数,其函数值为指针,即它带回来的值的类型为指针,当调用这个函数后,将得到一个“指向返回值为…的指针(地址),“类型名”表示函数返回的指针指向的类型”。

    “(函数参数表列)”中的括号为函数调用运算符,在调用语句中,即使函数不带参数,其参数表的一对括号也不能省略。其示例如下:

    int *pfun(int, int);

    由于“*”的优先级低于“()”的优先级,因而pfun首先和后面的“()”结合,也就意味着,pfun是一个函数。即:

    int *(pfun(int, int));

    接着再和前面的“*”结合,说明这个函数的返回值是一个指针。由于前面还有一个int,也就是说,pfun是一个返回值为整型指针的函数。

    我们不妨来再看一看,指针函数与函数指针有什么区别?

    int (*pfun)(int, int);

    通过括号强行将pfun首先与“*”结合,也就意味着,pfun是一个指针,接着与后面的“()”结合,说明该指针指向的是一个函数,然后再与前面的int结合,也就是说,该函数的返回值是int。由此可见,pfun是一个指向返回值为int的函数的指针。

    虽然它们只有一个括号的差别,但是表示的意义却截然不同。函数指针的本身是一个指针,指针指向的是一个函数。指针函数的本身是一个函数,其函数的返回值是一个指针。

  2. 用函数指针作为函数的返回值
    在上面提到的指针函数里面,有这样一类函数,它们也返回指针型数据(地址),但是这个指针不是指向int、char之类的基本类型,而是指向函数。对于初学者,别说写出这样的函数声明,就是看到这样的写法也是一头雾水。比如,下面的语句:

    int (*ff(int))(int *, int);
    我们用上面介绍的方法分析一下,ff首先与后面的“()”结合,即:

    int (*(ff(int)))(int *, int); // 用括号将ff(int)再括起来

也就意味着,ff是一个函数。
接着与前面的“*”结合,说明ff函数的返回值是一个指针。然后再与后面的“()”结合,也就是说,该指针指向的是一个函数。

这种写法确实让人非常难懂,以至于一些初学者产生误解,认为写出别人看不懂的代码才能显示自己水平高。而事实上恰好相反,能否写出通俗易懂的代码是衡量程序员是否优秀的标准。一般来说,用typedef关键字会使该声明更简单易懂。在前面我们已经见过:

int (*PF)(int *, int);

也就是说,PF是一个函数指针“变量”。当使用typedef声明后,则PF就成为了一个函数指针“类型”,即:

typedef int (*PF)(int *, int);

这样就定义了返回值的类型。然后,再用PF作为返回值来声明函数:

PF ff(int);

引用自:https://www.cnblogs.com/code1527/p/3249027.html
用函数指针作为函数的返回值

typedef的用法,C语言typedef详解

typedef的4种用法

在实际使用中,typedef 的应用主要有如下4种。

  1. 为基本数据类型定义新的类型名
    也就是说,系统默认的所有基本类型都可以利用 typedef 关键字来重新定义类型名,示例代码如下所示:
    typedef unsigned int COUNT;
    而且,我们还可以使用这种方法来定义与平台无关的类型。比如,要定义一个叫 REAL 的浮点类型,在目标平台一上,让它表示最高精度的类型,即:
    typedef long double REAL;
    在不支持 long double 的平台二上,改为:
    typedef double REAL;
    甚至还可以在连 double 都不支持的平台三上,改为:
    typedef float REAL;
    这样,当跨平台移植程序时,我们只需要修改一下 typedef 的定义即可,而不用对其他源代码做任何修改。其实,标准库中广泛地使用了这个技巧,比如 size_t 在 VC++2010 的 crtdefs.h 文件中的定义如下所示:
#ifndef _SIZE_T_DEFINED
#ifdef  _WIN64
typedef unsigned __int64    size_t;
#else
typedef _W64 unsigned int   size_t;
#endif
#define _SIZE_T_DEFINED
#endif
  1. 为自定义数据类型(结构体、共用体和枚举类型)定义简洁的类型名称
    以结构体为例,下面我们定义一个名为 Point 的结构体:
struct Point
{
    double x;
    double y;
    double z;
};

在调用这个结构体时,我们必须像下面的代码这样来调用这个结构体:

struct Point oPoint1={1001000};
struct Point oPoint2;

在这里,结构体 struct Point 为新的数据类型,在定义变量的时候均要向上面的调用方法一样有保留字 struct,而不能像 int 和 double 那样直接使用 Point 来定义变量。现在,我们利用 typedef 定义这个结构体,如下面的代码所示:

typedef struct tagPoint
{
    double x;
    double y;
    double z;
} Point;

在上面的代码中,实际上完成了两个操作:

  1. 定义了一个新的结构类型,代码如下所示:
struct tagPoint
{
    double x;
    double y;
    double z;
} ;

其中,struct 关键字和 tagPoint 一起构成了这个结构类型,无论是否存在 typedef 关键字,这个结构都存在。

  1. 使用 typedef 为这个新的结构起了一个别名,叫 Point,即:
    typedef struct tagPoint Point
    因此,现在你就可以像 int 和 double 那样直接使用 Point 定义变量,如下面的代码所示:
Point oPoint1={1001000};
Point oPoint2;

为了加深对 typedef 的理解,我们再来看一个结构体例子,如下面的代码所示:

typedef struct tagNode
{
    char *pItem;
    pNode pNext;
} *pNode;

从表面上看,上面的示例代码与前面的定义方法相同,所以应该没有什么问题。但是编译器却报了一个错误,为什么呢?莫非 C 语言不允许在结构中包含指向它自己的指针?

其实问题并非在于 struct 定义的本身,大家应该都知道,C 语言是允许在结构中包含指向它自己的指针的,我们可以在建立链表等数据结构的实现上看到很多这类例子。那问题在哪里呢?其实,根本问题还是在于 typedef 的应用。

在上面的代码中,新结构建立的过程中遇到了 pNext 声明,其类型是 pNode。这里要特别注意的是,pNode 表示的是该结构体的新别名。于是问题出现了,在结构体类型本身还没有建立完成的时候,编译器根本就不认识 pNode,因为这个结构体类型的新别名还不存在,所以自然就会报错。因此,我们要做一些适当的调整,比如将结构体中的 pNext 声明修改成如下方式:

typedef struct tagNode
{
    char *pItem;
    struct tagNode *pNext;
} *pNode;

或者将 struct 与 typedef 分开定义,如下面的代码所示:

typedef struct tagNode *pNode;
struct tagNode
{
    char *pItem;
    pNode pNext;
};

在上面的代码中,我们同样使用 typedef 给一个还未完全声明的类型 tagNode 起了一个新别名。不过,虽然 C 语言编译器完全支持这种做法,但不推荐这样做。建议还是使用如下规范定义方法:

struct tagNode
{
    char *pItem;
    struct tagNode *pNext;
};
typedef struct tagNode *pNode;
  1. 为数组定义简洁的类型名称
    它的定义方法很简单,与为基本数据类型定义新的别名方法一样,示例代码如下所示:
typedef int INT_ARRAY_100[100];
INT_ARRAY_100 arr;
  1. 为指针定义简洁的名称
    对于指针,我们同样可以使用下面的方式来定义一个新的别名:
typedef char* PCHAR;
PCHAR pa;

对于上面这种简单的变量声明,使用 typedef 来定义一个新的别名或许会感觉意义不大,但在比较复杂的变量声明中,typedef 的优势马上就体现出来了,如下面的示例代码所示:
int *(*a[5])(int,char*);
对于上面变量的声明,如果我们使用 typdef 来给它定义一个别名,这会非常有意义,如下面的代码所示:
// PFun是我们创建的一个类型别名
typedef int *(*PFun)(int,char*);
// 使用定义的新类型来声明对象,等价于int*(a[5])(int,char);
PFun a[5];
小心使用 typedef 带来的陷阱
接下来看一个简单的 typedef 使用示例,如下面的代码所示:

typedef char* PCHAR;
int strcmp(const PCHAR,const PCHAR);

在上面的代码中,“const PCHAR” 是否相当于 “const char*” 呢?

答案是否定的,原因很简单,typedef 是用来定义一种类型的新别名的,它不同于宏,不是简单的字符串替换(有关 typedef 和 #define 的区别,请猛击这里了解详情)。因此,“const PCHAR”中的 const 给予了整个指针本身常量性,也就是形成了常量指针“charconst(一个指向char的常量指针)”。即它实际上相当于“charconst”,而不是“const char*(指向常量 char 的指针)”。当然,要想让 const PCHAR 相当于 const char* 也很容易,如下面的代码所示:

typedef const char* PCHAR;
int strcmp(PCHAR, PCHAR);

其实,无论什么时候,只要为指针声明 typedef,那么就应该在最终的 typedef 名称中加一个 const,以使得该指针本身是常量。

还需要特别注意的是,虽然 typedef 并不真正影响对象的存储特性,但在语法上它还是一个存储类的关键字,就像 auto、extern、static 和 register 等关键字一样。因此,像下面这种声明方式是不可行的:
typedef static int INT_STATIC;
不可行的原因是不能声明多个存储类关键字,由于 typedef 已经占据了存储类关键字的位置,因此,在 typedef 声明中就不能够再使用 static 或任何其他存储类关键字了。当然,编译器也会报错,如在 VC++2010 中的报错信息为“无法指定多个存储类”。

引用自: http://c.biancheng.net/view/298.html
typedef的用法,C语言typedef详解

<think>好的,我现在需要帮用户解决如何在C/C++中使用typedef函数指针定义别名的问题。首先,我得回忆一下相关的知识。函数指针本身有点复杂,特别是语法部分容易出错。用户可能已经了解基本的函数指针声明,但现在想通过typedef简化代码,提高可读性。首先,我得明确typedef的作用,它用于创建类型别名。对于函数指针,正确的语法是关键。比如,直接声明一个函数指针可能是这样的:int(*ptr)(int, int);。但用typedef的话,需要将别名放在通常变量名的位置。例如,typedefint (*FuncPtr)(int, int);,这样FuncPtr就成了这个函数指针类型的别名。接下来,我需要分步骤说明如何定义和使用。可能需要先介绍函数指针的基本定义,然后对比使用typedef后的变化。同时,要确保语法正确,比如括号的位置和星号的位置不能错。用户可能容易在语法上出错,所以需要强调这一点。 然后,应用场景部分,用户可能想知道为什么用typedef更好。比如,简化函数指针的声明,特别是在作为参数传递或返回值时,代码会更简洁。例如,使用别名后,函数参数可以直接用FuncPtr,而不需要每次都写完整的函数指针类型,减少出错机会。 还要注意用户提供的引用内容,引用[1]提到typedef定义类型别名更推荐,引用[2]和[4]给出了具体的例子。需要结合这些例子,说明正确用法。同时,引用[3]提到了函数指针作为形参的情况,可以用typedef来简化声明。可能用户会混淆函数类型和函数指针类型的typedef,需要指出区别。比如,typedef intFunc(int, int);定义的是函数类型,而typedefint (*FuncPtr)(int, int);才是函数指针类型。这在声明变量时很重要,因为函数类型不能直接用来声明指针变量,必须加上星号。 另外,需要给出具体的代码示例,展示定义和使用过程。比如,如何用别名声明变量,如何赋值,以及如何调用函数。代码示例要清晰,避免语法错误,帮助用户理解。最后,生成的相关问题需要围绕用户可能进一步想知道的内容,比如与直接声明的区别、复杂函数指针的别名、常见错误等。这些问题可以帮助用户深入理解主题,并解决实际编程中可能遇到的问题。总结一下,回答的结构应该是:先介绍基本概念,然后分步骤讲解定义和使用方法,接着说明应用场景和优势,最后给出示例代码和相关问题。确保每一步都符合用户的要求,比如使用正确的中文,LaTeX格式的数学表达式(虽然这个问题可能不涉及数学公式,但如果有变量名之类的,可能需要用$...$),以及引用标记的正确添加。</think>### 如何使用`typedef`为函数指针定义别名 在C/C++中,`typedef`可以为复杂类型(包括函数指针)定义简洁的别名,提升代码可读性和可维护性。以下是具体步骤和示例: --- #### 一、函数指针的基本定义 函数指针指向函数的内存地址,其声明语法为: ```c 返回值类型 (*指针变量名)(参数列表); ``` 例如,指向`int add(int a, int b)`的指针: ```c int (*pfn)(int, int); // 直接定义函数指针变量 pfn = add; // 赋值 ``` --- #### 二、使用`typedef`定义函数指针类型别名 **语法规则**: ```c typedef 返回值类型 (*别名)(参数列表); ``` ##### 示例1:定义简单函数指针类型 ```c typedef int (*FuncPtr)(int, int); // 定义别名FuncPtr FuncPtr pfn = add; // 使用别名声明变量 ``` ##### 示例2:定义带复杂参数的函数指针类型 ```c typedef void (*Callback)(const char*, int); // 处理字符串和整形的回调函数类型 Callback cb = logger; // 声明回调变量 ``` --- #### 三、`typedef`的优势 1. **简化声明**:避免重复书写复杂的函数指针类型[^1]。 ```c // 未使用typedef void register_callback(void (*cb)(int)); // 使用typedef typedef void (*CallbackType)(int); void register_callback(CallbackType cb); ``` 2. **提高代码可读性**:别名明确表达类型用途(如`Comparator`、`EventHandler`)。 3. **统一接口**:在多个函数中复用同一函数指针类型。 --- #### 四、完整示例代码 ```c #include <stdio.h> // 定义函数原型 int add(int a, int b) { return a + b; } int sub(int a, int b) { return a - b; } // 使用typedef定义函数指针类型别名 typedef int (*MathFunc)(int, int); int main() { MathFunc func = add; printf("Result: %d\n", func(3, 2)); // 输出5 func = sub; printf("Result: %d\n", func(3, 2)); // 输出1 return 0; } ``` --- #### 五、常见错误与注意事项 1. **语法错误**:`typedef`的括号和星号位置必须正确。 ```c typedef int *FuncPtr(int, int); // 错误!实际定义的是返回int*的函数类型 typedef int (*FuncPtr)(int, int); // 正确 ``` 2. **函数类型与函数指针类型**: ```c typedef int Func(int, int); // 定义函数类型别名 Func* pfn = add; // 必须显式转换为指针 ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值