分析陈述,最基本的方法是类比代入法。 从最基本的陈述出发进行类比和简化来理解。 下面通过分析三个例子来详细说明如何使用该方法。
#1: int* (*a[5])(int, char*);
首先我们看到标识符名称a,“[]”的优先级高于“*”,a先与“[5]”组合。 所以 a 是一个数组。 该数组有 5 个元素。 每个元素都是一个指针。 指针指向“(int, char*)”。 显然,它指向一个函数,函数参数是“int,char*.”,返回值是“int*”。 好了,一篇结束了。 :)
#2: void (*b[10]) (void (*)());
b 是一个数组。 该数组有 10 个元素。 每个元素都是一个指针。 指针指向一个函数。 函数参数为“void (*)()”[注10],返回值为“void”。 完全的!
注意:这个参数也是一个指针,指向一个函数。 函数参数为空,返回值为“void”。
# 3. doube(*)() (*pa)[9];
pa 是一个指针。 指针指向一个数组。 该数组有 9 个元素。 每个元素都是“doube(*)()”(即指向一个函数的函数指针,这个函数的参数为空,返回值为yes”)。
C语言函数指针
函数在内存中具有物理位置,并且该位置可以分配给指针。 零点函数的地址是函数的入口点。 因此,可以使用函数指针来调用函数。 函数的地址是通过使用函数名获得的,不带任何括号或参数。 (这和获取数组地址的方法很相似,即只有数组名而没有下标时获取数组地址。)
如何声明函数指针变量?
要表明变量的类型是“返回值为 int 的函数指针”,可以使用以下声明语句:
int (*) ();
为了让编译器正确解释该语句,* 必须括在括号内。 如果缺少这对括号,则:
整数*();
意义完全不同。 将是一个函数的名称,其返回值为 int 类型的指针。
函数指针变量
C语言中规定函数总是占用一块连续的内存区域,函数名就是该函数占用的内存区域的首地址。 我们可以将函数的首地址(或入口地址)赋给一个指针变量,使指针变量指向该函数。 然后可以通过指针变量找到并调用该函数。 我们把这个指向函数的指针变量称为“函数指针变量”。
函数指针变量定义的一般形式为:
类型说明符(*指针变量名)();
“类型说明符”表示所引用函数的返回值的类型。 “(*指针变量名)”表示“*”后面的变量是已定义的指针变量。 末尾的空括号表示指针变量引用一个函数。
例如: int(*pf)();
表示pf是一个指向函数入口的指针变量,函数的返回值(函数值)是一个整数。
下面通过一个例子来说明如何以指针的形式实现函数调用。
(inta,intb){
如果(a>b);
;
主要的(){
(inta,intb);
int(*pmax)();
intx,y,z;
pmax=最大;
(“:/n”);
scanf("%d%d",&x,&y);
z=(*pmax)(x,y);
(“=%d”,z);
从上面的程序可以看出,以函数指针变量的形式调用函数的步骤如下:
1、先定义函数指针变量,如int(*pmax)(); 在后一个程序的第 9 行; 将 pmax 定义为函数指针变量。
2、将被调用函数的入口地址(函数名)赋值给函数指针变量,如程序第11行pmax=max;
3、使用函数指针变量调用函数,如程序第14行z=(*pmax)(x,y); 调用函数的一般形式为: (*指针变量名) (实参列表) 使用函数指针变量还应注意以下两点:
A。 函数指针变量不能进行算术运算,这一点与数组指针变量不同。 数组指针变量加或减一个整数可以移动指针指向后面或前面的数组元素,而函数指针的移动是没有意义的。
b. 函数调用中“(*指针变量名)”两边的括号是必不可少的。 * 不应被理解为求值操作。 这里只是一个符号。
指针函数
之前我们介绍过,所谓函数类型是指函数返回值的类型。 在C语言中,函数的返回值允许是指针(即地址)。 这种返回指针值的函数称为指针函数。
定义指针函数的一般形式是:
类型说明符 * 函数名称(形参列表)
....../* 函数体*/
函数名前的“*”号表示它是一个指针函数,即返回值是一个指针。 类型说明符指示返回的指针值所指向的数据类型。
喜欢:
int*ap(intx,inty)
....../* 函数体*/
表示ap是一个返回指针值的指针函数,它返回的指针指向一个整型变量。 下面的示例定义了一个指针函数,其返回值指向一个字符串。 该函数中定义了一个静态指针数组名称。 name数组最初分配了8个字符串,分别代表每周的名称和错误提示。 形参n表示星期名称对应的整数。 在主函数中,输入整数i作为实参,在语句中调用该函数并将i值传递给形参n。 函数中的语句包含条件表达式。 如果n值大于7或小于1,则将name[0]指针返回到主函数,并输出错误提示字符串“”。 否则,返回主函数输出的相应周名称。 main函数中的第7行是条件语句。 它的语义是,如果输入是负数(i),程序将停止运行并退出程序。 exit 是一个库函数。 exit(1)表示发生错误后退出程序。 exit(0)表示正常退出。
特别要注意函数指针变量和指针函数在写法和含义上的区别。 例如,int(*p)() 和 int*p() 是两个完全不同的量。 int(*p)()是一个变量描述,表示p是一个指向函数入口的指针变量。 函数的返回值是一个整数。 (*p) 两边的括号不能少。 int*p()不是变量描述而是函数描述,表明p是一个指针函数,其返回值是一个指向整数的指针。 *p 两边没有括号。 作为函数描述,形式参数最好写在括号内,以便更容易与变量描述区分开。 对于指针函数定义来说,int*p()只是函数头部分,一般应该有函数体部分。
主要的(){
因蒂;
字符*(intn);
(“:/n”);
scanf("%d",&i);
if(i("第几天:%2d-->%s/n",i,(i));
字符*day_n
ame(intn){
*名称[]={"",
"",
"",
"",
"",
"",
"",
“”};
((n7)?名称[0]:名称[n]);
该程序使用指针函数输入1到7之间的整数,并输出相应的周名称。 指针数组的描述以及使用元素值为指针的数组是指针数组。 指针数组是指针的有序集合。 指针数组的所有元素必须是具有相同存储类型并指向相同数据类型的指针变量。
指针数组描述的一般形式为:类型说明符*数组名[数组长度]
类型说明符是指针值所指向的变量的类型。 例如:int*pa[3]表示pa是一个指针数组,它有3个数组元素,每个元素值都是一个指向整型变量的指针。 通常可以使用指针数组来指向二维数组。 指针数组中的每个元素都被分配了二维数组每行的首地址,因此也可以理解为指向一维数组。 图 6-6 显示了这种关系。
inta[3][3]={1,2,3,4,5,6,7,8,9};
int*pa[3]={a[0],a[1],a[2]};
int*p=a[0];
主要的(){
因蒂;
for(i=0;i("%d,%d,%d/n",a[i][2-i],*a[i],*(*(a+i)+i));
for(i=0;i("%d,%d,%d/n",*pa[i],p[i],*(p+i));
在这个示例程序中,pa是一个指针数组,三个元素分别指向二维数组a的每一行。 然后使用循环语句输出指定的数组元素。 其中,*a[i]表示第i行第0列的元素值; *(*(a+i)+i)表示第i行第i列的元素值; *pa[i]表示第i行第i列的元素值; 由于p和a[0]相同,所以p[i]代表第0行第i列的值; *(p+i)表示第0行第i列的值。 读者可以仔细看看元素值的各种表示方式。 应该注意指针数组和二维数组指针变量的区别。虽然两者都可以用来表示二维数组,但是它们的表示方法和含义是不同的。