刚学 C 语言的朋友,是不是一碰到函数和指针凑一块儿就犯怵?想通过函数改个外面的变量吧,忙活半天变量还是老样子;想把函数当参数传给另一个函数,代码写出来全是错,编译器报错能刷满屏幕。其实啊,函数和指针结合看着难,把道理捋顺了,用起来可方便了。今天兔子哥就掰开了揉碎了讲这个事儿,带点例子,保证零基础也能看明白。
► 函数和指针结合到底是啥?为啥非要放一块儿用?
咱们先说说基础的,函数和指针结合,说白了就是用指针来操作函数,或者把指针当参数传给函数。那为啥要这么折腾呢?你想啊,普通函数的时候,有时候需要修改函数外面的变量,普通参数传进去的是副本,改了白改;这时候用指针,传变量的地址过去,函数里就能直接改原变量了,多方便。
还有啊,有时候咱们需要根据不同情况调用不同函数,比如排序的时候,想让用户自己选升序还是降序,这时候用函数指针就能灵活多了,不用写俩几乎一样的排序函数。你看,这就是结合起来用的好处,灵活、高效,还能少写不少重复代码。
► 怎么用指针当函数参数?实际写代码时咋用?
用指针当函数参数,其实就是把变量的地址传给函数。兔子哥给你举个例子,比如想写个交换两个整数的函数:
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
调用的时候这么写:int x=3, y=5; swap (&x, &y); 这样 x 和 y 就真的交换了。这里的关键是,函数参数是 int类型,调用时传的是 & x、&y(变量的地址),函数里用a、*b 访问变量本身。
那在啥场景下用呢?嵌入式开发里读写硬件寄存器,经常要传寄存器地址;算法里处理数组,传数组首地址比传整个数组省内存,尤其是大数组的时候。你想啊,传整个数组相当于复制一份,多浪费空间,传地址就一个指针的大小,多划算。
► 函数指针是啥玩意儿?能用来干啥实际活儿?
函数指针,就是指向函数的指针,它存的是函数在内存里的地址。定义的时候有点绕,比如 int (*p)(int, int); 这个 p 就是个函数指针,能指向参数是两个 int、返回值是 int 的函数。
那它能干嘛?最常见的是实现回调函数。比如写个通用的排序函数,让用户自己传比较函数。你看这个例子:
void sort (int *arr, int n, int (*compare)(int, int)) {
// 排序逻辑,比较的时候调用 compare 函数
}
int ascending(int a, int b) { return a > b; }
int descending(int a, int b) { return a < b; }
想升序排就调用 sort (arr, n, ascending),降序就用 descending,多灵活。这种用法在库函数里特别多,比如 qsort 就是这么干的。
► 不用指针和函数结合会咋样?有啥坑得避开?
要是该用指针的时候不用,麻烦就来了。比如前面说的交换函数,不用指针的话:
void swap(int a, int b) {
int temp = a;
a = b;
b = temp;
}
调用完 x 和 y 根本没变,因为传的是副本,白忙活。这时候你要是不知道问题出在哪,能调半天都找不到错。
还有用函数指针的时候,指针类型得和函数匹配,参数个数、类型、返回值都得一样,不然调用的时候轻则结果错,重则程序崩溃。比如把返回 void 的函数赋给返回 int 的函数指针,编译器可能不报错,但运行起来绝对出问题。
另外啊,别让函数指针指向局部函数,虽然 C 语言里一般不允许,但有些编译器扩展支持,用了容易出奇怪的错,这点得注意。
最后兔子哥说点自己的感受,函数和指针结合这块儿,刚开始确实容易晕,尤其是函数指针的定义,总把 * 和括号放错地方。我刚开始学的时候,就拿个小本子记例子,写一个划掉一个,慢慢就有感觉了。其实关键是理解指针就是地址,函数指针就是函数的地址,操作指针就是操作地址对应的东西。多写几个例子,比如用指针改数组,用函数指针做回调,练着练着就熟了。真不用怕,谁都是从不会到会的,对吧?希望这些能帮到你,有啥具体问题,咱们再细聊。
版权声明:除非特别标注,否则均为本站原创文章,转载时请以链接形式注明文章出处。
还木有评论哦,快来抢沙发吧~