C语言中的函数指针与指针函数 c语言中函数指针

函数是任何一门语言中必不可少的部分,正是由这些函数组成了程序。首先谈一下C语言中的函数指针与指针函数,再了解一下函数参数传递的相关原理。

1.函数指针与指针函数

(1) 函数指针 即指向这个函数的指针,定义为 数据类型 (*fun)(参数列表) ,()的优先级比*高,所以*fun加括号。如 void (*fun)(int*,int*);

(2)指针函数 即返回值是指针的函数,定义为 数据类型 * fun(参数列表). 如 char* fun(int*,int*);即返回值为char*型。

在C语言中,变量有它的地址,同理函数也是有地址的。那么把函数的地址赋给函数指针,再通过函数指针调用这个函数就可以了。

第一步: 定义函数指针,如 int (*pfun)(int*,int*);

第二步: 定义函数 如 int fun(int*,int*);

第三步: 把函数的地址赋给函数指针,即 pfun=fun;

第四步: 通过函数指针去调用这个函数 (*pfun)(p,q); //pfun是函数的地址,那么 *pfun当然就是函数本身了。

2.函数参数传递问题

在C语言中,有两种参数传递的方式 ,一种是值传递,另一种是指针传递。

值传递很好理解,即把实参的值传递给形参。

而指针传递传的是地址在C语言中,形参值的改变并不能改变实参的值,但形参所指向内容值的改变却能改变实参,这一点非常的重要,是指针传递的精华所在。

3. 指针函数

当函数的返回值为指针类型时,应该尽量不要返回局部变量的指针,因为,局部变量是定义在函数内部,当这个函数调用结束了,局部变量的栈内存也被释放了,因此,不能够正确的得到返回值。实际上,内存已经被释放了,但这个指针的地址已经返回过去了,但是这个地址已经是无效的了,此时,对这个指针的使用是很危险的。

4. 野指针

野指针并不是NULL,而是指向垃圾内存的指针。

有两种情况可以导致野指针:

(1) char* p;

(2)malloc,free

第一种情况是定义指针,但没有给指针赋地址,此时,对指针的使用是很危险的,因为你不知道它指向哪里,是个野指针。

第二种情况,malloc是在堆上分配内存,必须由用户手动释放,当释放之后,指针指向的内存已经释放掉了,但指针本身的地址还存在,即指向了一个无效的内存,所以这时的指针为野指针,必须把这个指针p=NULL.

5. 下面举个例子说明上述几种情况

C语言中的函数指针与指针函数 c语言中函数指针
#include <stdio.h>

#include <string.h>

#include <stdlib.h>

#include <unistd.h>

void fun1(int*,int*);

void fun2(int*,int*);

char* fun(char*,char*);//指针函数,即返回值为指针的函数

int main(){

//定义3个函数指针

void (*pfun1)(int*,int*);

void(*pfun2)(int*,int*);

char*(*pfun)(char*,char*);//定义返回值为指针的函数指针

int *p;

int *q;

int a=10;

int b=20;

p=&a;//整形指针变量的初始化

q=&b;

printf("%dn",*p);

printf("%dn",*q);

pfun1=fun1;//把函数fun的地址赋值给函数指针pfun

pfun2=fun2;

(*pfun1)(p,q);//用函数指针去调用函数,pfun是fun的地址,那么*pfun当然就是函数本身了

printf("%dn",*p);

printf("%dn",*q);

//当交换两个指针时,发现值并没有发生改变

//在C语言中,形参的改变并不能改变实参,实参中p指向a的地址,q指向b的地址,在形参中,把两个地址互换,即形参的p指向b的地址,q指向a的地址,但并不能改变实参的值,除非改变地址中的内容值

(*pfun2)(p,q);

printf("%dn",*p);

printf("%dn",*q);

//此时p与q指向的值发生了变化,由于把地址中的内容交换了,所以交换了p,q

pfun=fun;

char* x="ab";

char* y="bc";

char* s=(*pfun)(x,y);

printf("%sn",s);

//free(s);//s指向这个堆内存,所以malloc之后要释放

s=NULL;

if(s!=NULL){//释放掉这个内存后,指针仍然不为空,此时的指针称为野指针,所以要把s=NULL

printf("%sn",s);

}

//对于野指针,有两种情况

//第一种情况: char* p;只声明了字符型指针,但没明确指向的地址,此时,用这个指针是很危险的,因为这个指针是野指针

//第二种情况: malloc()之后,没有free()之后,没有把指针设置为空,因为此时指针仍然存有地址,但是这个地址已经是无效的,所以对这个指针的使用是很危险的

return 0;

}

void fun1(int*p,int*q){

int* temp=p;

p=q;

q=temp;

}

void fun2(int*p,int*q){

int temp;

temp=*p;

*p=*q;

*q=temp;

}

char* fun(char*p,char* q){

//char a[]="abc";//定义一个内存空间,局部变量栈上内存

//char* s=a;

//return s;//在这函数结束之后,char型指针被释放掉,因此不能正确返回

//因此,最好别返回一个局部变量指针

//(1)解决方法:把数组变成静态,即 static char a[]="abc";静态内存在函数结束后不会被释放

//(2)申请堆内存

//(3)定义为常量区

//char *s=(char*)malloc(sizeof(char*)*10);

// strcpy(s,"abc");

char* s1="ssss"; //定义一个指针变量指向字符串,在C中,字符串被存放在常量区,静态存储区域,因此,在这个函数结束之后,这个地址仍然是有效的,即常量区的内存没有被释放掉,因此能够返回值

return s1;

}

1. fun1函数

fun1函数中交换地址,并不能交换两个指针指向的值,因为形参的改变不能引起实参的改变。

2. fun2函数

fun2函数交换的是地址里面的内容,所以能交换两个指针指向的值。

3. fun函数

(1)fun函数里面定义的a是个局部变量,在函数返回之后这块内存会被释放掉。因此,为了得到返回值,可以声明为 static char a[]=""abc";

(2)malloc申请的是堆内存,因此,可以得到返回值,但必须free掉这块内存,同时将p=NULL,避免野指针。

(3)可以定义char* s=字符串,在C语言中,字符串是存放是静态常量区,因此,函数结束后,那块内存不会被释放掉。可以得到返回值。

因此,不能返回局部指针变量。

C语言中,形参只有在传递时才分配内存单元,实参到形参的传递是单向传递,因此,形参的改变并不能引起实参的改变,另外,实参与形参占据着不同的内存单元。

  

爱华网本文地址 » http://www.413yy.cn/a/25101014/198619.html

更多阅读

图像处理中的卷积与模板 图像处理 卷积

图像处理中的卷积与模板2011-04-25 11:16转载自 deepthink_2010最终编辑 shuting_guo1.使用模板处理图像相关概念:模板:矩阵方块,其数学含义是一种卷积运算。卷积运算:可看作是加权求和的过程,使用到的图像区域中的每个像素分别与卷积核(

声明:《C语言中的函数指针与指针函数 c语言中函数指针》为网友坦诚相待分享!如侵犯到您的合法权益请联系我们删除