C函数和指针

一些复杂的声明

  • 声明时可使用的符号:
    * --- 表示一个指针
    ()--- 表示一个个函数
    []--- 表示一个数组
    
- 示列:
    ```
    int board[8][8];        //声明一个内含数组的数组

    int ** ptr;            //声明一个指向指针的指针,被指向的指针指向int

    int * risks[10];        //声明一个内含10个元素的数组,每个元素都是一个指向int的指针

    int (* rusks)[10];      //声明一个指向数组的指针,该数组内含10个int类型的值

    int (* uuf)[3][4];      //声明一个3 X 4的二维数组,每个元素都是指向int的指针

    int (* uuf)[3][4];      //声明一个指向3 X 4二维数组的指针,该数组中内含int类型的值

    int (* uuf[3])[4];      //声明一个内含3个指针元素的数组,其中每个指针都指向一个内含4个int类型元素的数组。

    ```
- `*`、`()`、`[]`的优先级及结合规则:
    1. 数组名后面的`[]`和函数名后面的`()`具有相同的优先级。比`*`的优先级高。
    2. 从左往右结合。
    
- 根据这些规则可进行如下形式的声明:

char * fump(int); //返回字符指针的函数
char (* frump)(int); //指向函数的指针,该函数的返回类型为char
char (* flump[3])(int); //内含3个指针的数组,每个指针都指向返回值为char的函数


函数和指针

#### 什么是函数指针
- 函数也有地址,因为函数的机器语言实现由载入内存的代码组成。
- 指向函数的指针中储存着**函数代码的起始处的地址**。

#### 声明函数指针
> 声明数据指针时,必须声明指针所指向的数据类型。
> 同样,声明函数指针时,**必须声明函数指针指向的函数类型**;为了指明函数类型,要指明函数签名(即,函数的返回类型和参数类型)。

eg:有下面函数原型:

void ToUpper(char *); //把字符串中的字符转换成大写字符

ToUpper()函数的类型是带`char *`类型参数,返回类型是`void`的函数。  
声明一个指针pf指向该函数类别:

void (pf)(char); //pf是一个指向函数的指针;把函数名ToUpper替换成表达式(*pf)

声明一个指向某类型函数的指针 最简单的方式:
    1. 写出该函数的原型
    2. 把函数名替换成(`*pf`)形式的表达式。即可创建函数指针声明(pf为指向该类型函数的指针)。
    
使用typedef:

typedef void (*V_FP_CHARP)(char *);

void show (V_FP_CHARP fp, char *);

V_FP_CHARP pfun


note:

void *pf(char *); //pf不是函数指针,是一个返回字符指针的函数

声明了函数指针以后,可以把类型匹配的*函数地址*赋给函数指针。这种上下文中,函数名可用于表示函数地址。eg:

void ToUpper(char *);
void ToLower(char *);
int round(double);

void (*pf)(char *);

pf = ToUpper; //有效
pf = ToLower; //有效

pf = round; //无效,round与指针类型不匹配
pf = ToLower(); //无效,ToLower()不是地址,且ToLower()的返回值是void,没有返回值,不能在赋值语句中进行赋值。


#### 使用函数指针
> 可以使用数据指针访问数据,同样也可以使用**函数指针访问函数**

- 存在两种语法:两种用法都可以
eg:
    ```
    void ToUpper(char *);
    void ToLower(char *);
    void (*pf)(char *);
    char mis[] = "Nina Metier";

    pf = ToUpper;
    (*pf)(miss)    //把ToUpper作用于语法1

    pf = ToLower;
    pf(miss);     //把ToLower作用于语法2
    ```
    - 语法1:由于pf指向ToUpper函数,`*pf`相当于ToUpper函数,所以`(*pf)(miss)`和`ToUpper(miss)`相同;从声明可看出ToUpper和`*pf`是等价的。
    - 语法2:由于函数名是指针,所以指针和函数名可以互换使用,所以`pf(miss)`和`ToLower(miss)`相同;从pf的赋值表达式语句可看出ToLower和pf是等价的
    - 历史原因:贝尔实验室的C和UNIX采用的是语法1,伯克利的UNIX采用的是语法2;为保证兼容,ANSI C认为`(*pf)(miss)`与`pf(miss)`等价。

- 函数指针的常见用法:
    1. 作为函数的参数:
    ```
    void show(void (* fp)(char *), char * str);    //声明了两个形参,fp--函数指针(fp指向的函数接受char *类型的参数,返回值为void),str--数据指针(str指向一个char类型的数值)
    
    //调用函数:
    show(ToLower, miss);  //show()使用ToLower()函数:fp = ToLower
    
    show(pf, miss);    //show()使用pf指向的函数: fp = pf
    
    //show()函数定义
    void show(void (* fp)(char *), char * str)
    {
        (*fp)(str);    //把所选函数作用于str,用fp指向的函数转换str
        puts(str);     //显示结果
    }
    ```
note:带返回值的函数作为参数传递给另一个函数有两种方式:

function1(sqrt); //传递sqrt函数的地址; 假设function1()代码中会使用该函数
function2(sqrt(4.0)); //传递sqrt函数的返回值; 先调用sqrt()求值,把返回值传递给function2()


#### 使用函数名的4种方法:定义函数、声明函数、调用函数、作为指针

int comp(int x, int y); //函数原型中的函数名
status = comp(q, r); //函数调用中的函数名
int comp(int x, int y) //函数定义中的函数名
{

}
pfunct = comp; //在赋值表达式语句中,作为指针的函数名
slowsort(arr, n, comp); //作为指针参数的函数名

> 参考资料:C primer Plus
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值