c 语言函数与指针基础
第一章. 指向函数的指针
如果在程序中定义了一个函数,编译的时候就会把函数的源代码转换为可执行代码并分配一段存储空间。这就和指针的定义联系起来了。
程序中,函数名代表函数的起始地址。可以这么说函数名就是函数的指针!
我们先定义一个指向函数的指针变量,举个例子
int(*p)(int,int)
这个形式为何这样写,()为何要把*与 p 全包含起来,相信大家也有这个疑惑
int 代表了函数类型,就是函数的返回值类型。 (int,int)代表了这个函数有两个 int 参数。这两个方面很基础。
与 p 的括号不可以省略,表示 p 与先结合,是指针变量,然后再与后面的()结合,所以很好理解了,该指针变量不是指向一般的变量
,而是指向函数。
如果因为你的理解不清晰,或者小错误写成了 intp(int,int)它们的理解就千差万别了。()优先级高于相当于 int*(p(int,int)),
这就是声明了一个 p 函数,返回值变成了指向整型变量的指针了!!!!!!(如果不懂的话继续往下看第二章就懂了)
可能大家不是很理解,来看一个比较直观的例子。(求两数的最大值,超级简单的哦)
1.函数名调用函数
2.指针变量调用它指向的函数
注重里面的细节哦
比如程序中 p=max 千万不要写成 p=max(a,b)
代表的意义只是把 max 入口地址赋值给指针变量 p,并不涉及实参与形参的结合问题,小心哦
指向函数的指针变量不可以进行算数运算,如 p+n,p++都是不可以的,因为没有意义,电脑不干!
有人问学习指针有啥用,从上面看似乎把程序变得更加复杂了
来,我们看下面这个程序
如果我们用函数就要写 c=max(a,b),c=min(a,b)
用指针的话很简单 c=(*p)(a,b)是不是简便了一点
通过判断给 p 指向不同函数,这样的思路更加的清晰,我们在写项目的时候往往函数很多很多,运用指针会给你简洁的排版,清晰的
思路,想用哪一个用哪一个。
上面我们所讲述的函数参数都是整型参数
下面我们来加点难度
用指向函数的指针作函数参数,指向函数的指针变量的一个重要用途是把函数的入口地址作为参数传递到其他函数。
来我们不讲那些理论难以理解的。
先看个题目:有两个整数 a 和 b,由用户输入 1,2,3.如果输入 1,程序就给出 a,b 中的最大值,输入 2,就给出 a,b 中最小值,输入 3 就给出
a,b 之和。
这种方法把程序变得非常简便非常清晰。用大众的话语来讲,就是用一个大盆子里放了许多小碗,你需要用啥小碗,你拿哪一个。
定义了三个我们需要用的函数,我再多加一个函数,这个函数就相当于那个大盆,我们现在就思考如何让他们联系在一起,指针
就非常有用了,多看看程序将他们分布思考,结构化程序设计就是要清晰!
接下来给大家留下了一些小问题,来拓宽大家的知识面,比如积分问题也可以用这种方法设计程序,当然先要掌握算法,程序设计
需要清晰思路,多写写,以上给大家的例题,笔者都一一敲过。(vs2019)程序设计思路非常重要,谢谢大家!
二.返回指针的函数
例如 int*a(int x,int y);
a 是函数名,得到它之后能得到一个 int*形指向整型数据的指针
通用形式为 类型名*函数名(参数列表)
下面这个程序“有 a 个学生,每个学生有 b 门成绩的课程,要求用户在输入学生序号以后,能输出该学生的全部成绩”
#include<stdio.h>
int main()
{
int score[][4] = { {60,70,80,90},{56,89,67,88},{34,78,90,66} };
float search(float(pointer)[4], int n);
float* p;
int i, k;
printf("enter the number of the student:");
scanf_s("%d", &k);
printf("The score of the NO%d are :\n", k);
p = search(score, k);
for (i = 0;i < 4;i++)
printf("%5.2f\t", *(p + i));
printf("\n");
return 0;
}
float search(float(pointer)[4], int n)
{
float* pt;
pt = *(pointer + n);
return(pt);
}
这个程序对于初学者是很难理解的,你要弄清楚指针含义才可以
我们先来看 float*search()这个函数的返回值是指针,因为没有括号,和上一章对比着看,我们往下看函数的定义,里面定义了一个指针 pt
返回值也就是 pt 这也就没有问题
第二个重点是 float(*pointer)[4] ,以我们平常的思路来看,这是一个形式参数,我们要注意[4],这个是个关键,说明一行四个元素
p=search(score,k)其中 score 代表第 0 行开头的地址!!!!!!如果没有这个[4],这个 score 可能会代表 0 行 0 列的地址。这些细微的差别是非常重要的。
pt = *(pointer + n);这一步代表 pt 的值是 &score[n][0] 为什么?
pointer 指向 0 行的开头,+n 就是加行
如果列要变化,假设变化为 k,((pointer+n)+k)则是求出的值(这边比较难以理解)
#include<stdio.h>
int main()
{
float score[][4] = { {60,70,80,90},{56,89,67,88},{34,78,90,66} };
float search(float(pointer)[4]);
float* p;
int i, j;
for(i=0;i<3;i++)
{
p = search(score + i); //调用 search 函数,不及格返回地址,几个的话返回 NULL
if (p == *(score + i)) //p 不是 NUll,这是个小判断
{
printf("NO.%d score:", i);
for (j = 0;j < 4;j++)
printf("%5.2f", *(p + j));
printf("\n");
}
}
return 0;
}
float search(float(pointer)[4])
{
int i = 0;
float* pt;
pt = NULL;
for (;i < 4;i++)
if ((pointer + i) < 60) pt = *pointer;
return pt;
}
我们来剖析下这个程序的思路,search 函数用于检查一个学生有没有不及格的课程,如何检查,通俗易懂来看,数组按行提出来,每行有四个元素
一个一个检查与 60 谁大,如果有不及格,直接给他返回 main 函数,在 main 函数中指针变量的值赋值给 p 再进行 if 语句的判断。
课后拓展:
#include<stdio.h>
#include<string.h>
int main()
{
void sort(char* name[], int n);
void print(char* name[], int n);
char* name[] = { "Follow me","BASIC","Great Wall","FORTRAN","Computer design" };
int n = 5;
sort(name, n);
print(name, n);
return 0;
}
void sort(char* name[], int n)
{
char * temp;
int i, j, k;
for (i = 0;i < n - 1;i++)
{
k = i;
for (j = i + 1;j < n;j++)
if (strcmp(name[k], name[j]) > 0)k = j;
if(k!=i)
{
temp = name[i];name[i] = name[k];name[k] = temp;
}
}
}
void print(char* name[], int n)
{
int i;
for (i = 0;i < n;i++)
printf("%s\n", name[i]);
}
最后这串代码是数组与多重指针,大家可以了解一下,举一反三。
版权声明: 本文为 InfoQ 作者【赫鲁小夫】的原创文章。
原文链接:【http://xie.infoq.cn/article/b3a58a6f9299f37f298662b27】。
本文遵守【CC BY-ND】协议,转载请保留原文出处及本版权声明。
评论