[TOC]
每个C程序都至少有一个函数,即主函数 **main()** ,所有简单的程序都可以定义其他额外的函数,格式如下:
```
返回类型 函数名称(参数1类型 参数1, 参数2类型 参数2, ...){}
```
函数还有很多叫法,比如方法、子例程或程序,等等
## 函数调用
[传值调用](https://www.runoob.com/cprogramming/c-function-call-by-value.html "C 中传值方式调用函数") 如:int func_name(int a)
[引用调用](https://www.runoob.com/cprogramming/c-function-call-by-pointer.html "C 中引用方式调用函数") 如:int func_name(int &a)
## 函数指针
函数指针是指向函数的指针变量,通常我们说的指针变量是指向一个整型、字符型或数组等变量,而【函数指针】是指向函数。
### **定义函数指针**:用(\*标识符)替换函数名,剩下照抄
```
int max(int a , int b){
return a>b?a:b;
}
//定义函数指针:先复制int max(int a , int b),然后将函数名替换为(*标识符)
int (*p)(int a , int b)=NULL;//任何指针都可以指向null,这时候还未执行max
//可以不加NULL吗,可以的 int (*p)(int a , int b); ,如果不指向null,第一时间想用这段内存时它却可能指向不是期望的内存,所以一般用null初始化新定义的指针
//定义函数指针时可以省略形参
int (*p)(int , int)=NULL;
```
用函数名给函数指针赋值
```
int (*pp)(int , int)=NULL;
pp=max;
```
### **函数指针的调用函数**
* 1、直接用函数指针替换函数名的方式调用
* 2、指针的基本操作去调用,取\*运算再调用
>[danger]不要和基本指针联系在一起,只需记得这两种方法就可以了
```
//原来调用函数
max(1,2);
//直接用函数指针替换函数名的方式调用函数
pp(1,2);
//指针的基本操作去调用,取\*运算再调用
(*pp)(1,2)
```
### **函数指针的用法(实现回调函数)**
回调函数(以函数指针为参数的函数)
```
int max(int a , int b){
return a>b?a:b;
}// 指针是int (*p)(int , int)
int min(int a , int b){
return a<b?a:b;
}// 指针是int (*p)(int , int)
//定义一个回调函数:(以函数指针为参数的函数就是回调函数)
void printData(int (*p)(int , int), int a, int b){
print("%d\n",p(a,b));
}
int main(){
//定义上面定义的回调函数的函数指针
void (*pp)(int (*p)(int , int), int a, int b)=printData;
//省略掉形参
void (*pp)(int (*)(int , int), int , int )=printData;
//调用上面定义的回调函数
pp(max,1,2);//求最大值 (*pp)(max,1,2)
pp(min,1,2);//求最小值(*pp)(min,1,2)
}
```
## **typedef**
### **基本用法(给已存在的类型起别名)**
```
#include <stdio.h>
typedef int INT;//INT是int的别名
int main(){
int a=1;
INT a=1;//d等于int a=1
}
// 步骤 将INT a=1中的INT替换为 typedef int INT; 得到typedef int a=1 然后去掉typedef 得到int a=1
```
### **再函数指针中的使用**
```
int max(int a , int b){
return a>b?a:b;
}// 指针是int (*pf)(int , int)
int main(){
typedef int(*pfunc)(int, int);//给指针定义别名叫pfunc
pfunc pf=max;
print("%d\n",pf(1,2))
}
//ypedef int(*pfunc)(int, int);拿下来 去掉ypedef 得到int(*pfunc)(int, int);
//然后将pfunc替换成pf得到int (*pf)(int , int)
```
typedef是为了简化回调函数的
```
int max(int a , int b){
return a>b?a:b;
}// 指针是int (*pf)(int , int)
//定义一个回调函数:(以函数指针为参数的函数就是回调函数)
void printData(int (*pf)(int , int), int a, int b){
print("%d\n",pf(a,b));
}
//调用回调函数
void (*pf)(int (*)(int , int), int , int )=printData;
pf(1,2);
//简化后
int max(int a , int b){
return a>b?a:b;
}// 指针是int (*pf)(int , int)
typedef int (*pf)(int , int);
void printData(pf P, int a, int b){
print("%d\n",P(a,b));
}
```
### **再结构体中定义别名**
```
typedef struct Node{
int data;
struct Node* next;
}NODE,*LPNODE,ARRAY[3];
//怎么看呢?不要看中间{}里的的代码
//typedef struct Node NODE,*LPNODE,ARRAY[3];
//和 int a,b,c等效int a;int b; int c;一样,可以得出:
//typedef struct Node NODE 结构体别名
//typedef struct Node* LPNODE结构体指针别名
//typedef struct Node ARRAY[3] 结构体数组别名
```
## **万能指针充当函数指针**
[函数指针](https://www.bilibili.com/video/BV1tL411M77o?p=3)
万能指针:空类型的指针void*
万能指针在操作任何类型指针,在使用前必须做强制类型转换
万能指针操作基本数据类型
```
void* p=NULL;
int a=0;//定义a变量
p=&a;//p指向a(p指向a的内存地址) 它可以指向任何类型这里是指向int
//使用前要先转换成想要的类型(int *)p 然后做*运算 *(int *)p
printf("%d\n", *(int *)p);
void* p=NULL;
float b=0.0f;//定义b变量
p=&b;//p指向b(p指向b的内存地址) 它可以指向任何类型这里是指向float
//使用前要先转换成想要的类型(float *)p 然后做*运算 *(float *)p
printf("%f\n", *(float *)p);//等价于float* pp=(float*)p; printf("%f\n", *pp);
```
万能函数当作函数指针
```
void print(){
printf("万能函数当作函数指针");
}
p=print;
```
- Visual Studio 2022安装到非C盘
- vscode轻量编辑器
- c#(csharp)
- .net平台区别
- 常用单词
- 关键字
- 操作符(运算符)
- 标识符(命名规范)
- 开始
- 变量
- 常量
- 数据类型
- 值类型
- 变量数据类型
- 枚举类型enum(常量集合)
- 结构类型struct(结构体)
- 元组类型
- 可null类型(T?)
- 引用类型
- 数组(array)
- 集合(List)
- 内置引用类型
- object
- string
- Dynamic(动态类型)
- delegate委托(代理)类型
- 自定义引用类型
- 接口(interface)
- 类class
- record(定义一个引用类型)
- 指针类型(仅用于非安全代码)
- get和set访问器
- delegate委托
- delegate实现发布订阅与事件
- 类型转换
- 合并操作符??
- 类相关
- Partial 部分类
- 类定义以及访问修饰符(封装)
- abstract抽象类与sealed密封类
- virtual虚方法
- 接口interface
- C# 预处理器指令
- C#技术栈
- 判断(流程控制)与三元运算
- if
- switch
- 三元运算
- 循环
- while 循环
- for循环
- foreach循环
- do...while 循环
- 文件操作
- 其他
- 多开
- c++
- 基本语法
- c++数据类型
- 变量和常量
- 运算符
- 分支结构(判断)
- 循环
- c++指针
- 函数
- 内置函数
