C++ 指针函数和函数指针有什么区别
来源:互联网 发布:产品展示动画制作软件 编辑:程序博客网 时间:2024/05/18 00:15
C++ 指针函数和函数指针有什么区别
这两个概念都是简称,指针函数是指带指针的函数,即本质是一个函数。我们知道函数都有返回类型(如果没有返回值,则为无值型),只不过指针函数返回类型是某一类型的指针(返回的是地址)。
返回类型标识符 *返回名称(形式参数表)
{ 函数体 }
返回类型可以是任何基本类型和复合类型。 事实上每一个函数,即使它不带有返回某种类型的指针,它本身都有一个入口地址,该地址相当于一个指针。比如函数返回一个整型值,实际上也相当于返回一个指针变量的值,不过这时的变量是函数本身而已,而整个函数相当于一个“变量”。例如下面一个返回指针函数的例子(VC++ 编译通过):
#include <iostream>
using namespace std;
int main()
{
float *find(float(*pionter)[4],int n);
static float score[][4]={{60,70,80,90},{56,89,34,45},{34,23,56,45}};
float *p;
int i,m;
printf("Enter the number to be found:");
scanf("%d",&m);
printf("the score of NO.%d are:\n",m);
p=find(score,m);
for(i=0;i<4;i++)
printf("%5.2f\t",*(p+i));
return 0;
}
float *find(float(*pionter)[4],int n)/*定义指针函数*/
{
float *pt;
pt=*(pionter+n);
return(pt);
}
学生学号从0号算起,函数find()被定义为指针函数,形参pointer是指针指向包含4个元素的一维数组的指针变量。pointer+1指向score的第一行。*(pointer+1)指向第一行的第0个元素。pt是一个指针变量,它指向浮点型变量。main()函数中调用find()函数,将score数组的首地址传给pointer.
2,“函数指针”是指向函数的指针变量,因而“函数指针”本身首先应是指针变量,只不过该指针变量指向函数。这正如用指针变量可指向整型变量、字符型、数组一样,这里是指向函数。如前所述,C在编译时,每一个函数都有一个入口地址,该入口地址就是函数指针所指向的地址。有了指向函数的指针变量后,可用该指针变量调用函数,就如同用指针变量可引用其他类型变量一样,在这些概念上一致的。函数指针有两个用途:调用函数和做函数的参数。
数据类型标志符 (*指针变量名)(参数) 。
下面的程序说明了函数指针调用函数的方法(VC++ 编译通过):
int max(int x,int y){ return(x>y?x:y); }
void main()
{
int (*ptr)(int,int);
int a,b,c;
ptr=max;
cin>>a>>b;
c=(*ptr)(a,b);
cout<<"a="<<a<<" b="<<b<<" c="<<c<<endl;
} }ptr是指向函数的指针变量,所以可把函数max()赋给ptr作为ptr的值,即把max()的入口地址赋给ptr,以后就可以用ptr来调用该函数,实际上ptr和max都指向同一个入口地址,不同就是ptr是一个指针变量,不像函数名称那样是死的,它可以指向任何函数 。在程序中把哪个函数的地址赋给它,它就指向哪个函数。而后用指针变量调用它,因此可以先后指向不同的函数,不过注意,指向函数的指针变量没有++和--运算,用时要小心。
指针函数应用举例:建立链表,插入,删除接点
#include <iostream>
using namespace std;
#define NULL 0
struct student
{long num;
float score;
student *next;
};
int n;
int main()
{ student *creat(void);
student *del(student *,long);
student *insert(student *,student *);
void print(student *);
student *head,*stu;
long del_num;
cout<<"input records:"<<endl;
head=creat(); //返回头指针
print(head); //输出全部结点
cout<<endl<<"input the deleted number:";
cin>>del_num; //输入要删除的学号
while(del_num!=0)
{head=del(head,del_num); //删除后链表的头地址
print(head); //输出全部结点
cout<<"input the deleted number:";
cin>>del_num;
}
cout<<endl<<"input the inserted record:"; //输入要插入的结点
stu=new student; //开辟一个新结点
cin>>stu->num>>stu->score;
while(stu->num!=0)
{head=insert(head,stu); //返回地址
print(head); //输出全部结点
cout<<endl<<"input the inserted record:"; //输入要插入的结点
stu=new student;
cin>>stu->num>>stu->score;
}
return 0;
}
student *creat(void) //建立链表的函数
{student *head;
student *p1,*p2;
n=0;
p1=p2=new student; //开辟一个新单元,并使p1,p2指向它
cin>>p1->num>>p1->score;
head=NULL;
while(p1->num!=0)
{n=n+1;
if(n==1) head=p1;
else p2->next=p1;
p2=p1;
p1=new student;
cin>>p1->num>>p1->score;
}
p2->next=NULL;
return(head);
}
student *del(student *head,long num) //删除结点的函数
{student *p1,*p2;
if (head==NULL) //是空表
{cout<<"list null!"<<endl; return(head);}
p1=head; //使p1指向第一个结点
while(num!=p1->num && p1->next!=NULL) //p1指向的不是所要找的结点且后面还有结点
{p2=p1; p1=p1->next;} //p1后移一个结点
if(num==p1->num) //找到了
{if(p1==head) head=p1->next; //若p1指向的是首结点,把第二个结点地址赋予head
else p2->next=p1->next; //否则将下一结点地址赋给前一结点地址
cout<<"delete:"<<num<<endl;
n=n-1;
}
else cout<<"cannot find "<<num; //找不到该结点
return(head);
}
student *insert(student *head,student *stud) //插入结点的函数
{student *p0,*p1,*p2;
p1=head; //使p1指向第一个结点
p0=stud; //指向要插入的结点
if(head==NULL) //原来的链表是空表
{head=p0;p0->next=NULL;} //使p0指向的结点作为头结点
else
{while((p0->num>p1->num) && (p1->next!=NULL))
{p2=p1; //使p2指向刚才p1指向的结点
p1=p1->next;} //p1后移一个结点
if(p0->num<=p1->num)
{if(head==p1) head=p0; //插到原来第一个结点之前
else p2->next=p0; //插到p2指向的结点之后
p0->next=p1;}
else
{p1->next=p0; p0->next=NULL;}} //插到最后的结点之后
n=n+1; //结点数加1
return (head);
}
void print(student *head) //输出链表的函数
{student *p;
cout<<"Now,These "<<n<<" records are:"<<endl;
p=head;
if(head!=NULL)
do
{cout<<p->num<<" "<<p->score<<endl;
p=p->next;
}while(p!=NULL);
}
int *p[n] 与int(*p)[n]区别
int*p[n]------p是一个指针数组,它由n个指向整型数据的指针元素组成 (含有n个指针元素)
int (*p)[n]----- p是一个指针(数组指针),指向int[n]的数组(它指向一个由n个int元素构成的数组)
#include <iostream>
using namespace std;
int main()
{
int *p[4];
int a=1,b=2,c=3,d=4;
p[0]=&a;
p[1]=&b;
p[2]=&c;
p[3]=&d;
int (*pp)[4];
//pp[0]=&a;//error
int aa[4]={5,6,7,8};
pp=&aa; // 换成aa 是错误的,定义的pp元素个数要与aa相同才可以赋值
cout<<*(p[0])<<" "<<*(pp[0])<<endl;
return 0;
}
#include <iostream>
#include <typeinfo>
using namespace std;
int main()
{
int vInt=10;
int arr[2]={10,20};
int *p=&vInt;
int **p2p=&p;
int *parr[2]={&vInt,&vInt};
int (*p2arr)[2]=&arr;
cout<<"Declaration [int vInt=10] type=="<<typeid(vInt).name()<<endl;
cout<<"Declaration [arr[2]={10,20}] type=="<<typeid(arr).name()<<endl;
cout<<"Declaration [int *p=&vInt] type=="<<typeid(p).name()<<endl;
cout<<"Declaration [int **p2p=&p] type=="<<typeid(p2p).name()<<endl;
cout<<"Declaration [int *parr[2]={&vInt,&vInt}] type=="<<typeid(parr).name()<<endl;
cout<<"Declaration [int (*p2arr)[2]=&arr] type=="<<typeid(p2arr).name()<<endl;
return 0;
}
运行的结果如下:(前面加了行号#XX)
#01 Declaration [int vInt=10] type==int
#02 Declaration [arr[2]={10,20}] type==int *
#03 Declaration [int *p=&vInt] type==int *
#04 Declaration [int **p2p=&p] type==int * *
#05 Declaration [int *parr[2]={&vInt,&vInt}] type==int **
#06 Declaration [int (*p2arr)[2]=&arr] type==int (*)[2]
#02, 在编译器看来数组只是相对应类型的指针类型。
当把数组传递给函数作为参数的时候,传递的是指针,所以可以利用参数来修改数组元素。这个转化是编译器自动完成的。也就是说这里编译器自动完成了int[]类型到int *的转化,
void f(int[]);
int a[2]={10,20};
f(a);//这行等价于编译器完成的函数转化f(int *p)
#05:指针数组的编译器内部表示也是对应类型的指针。
#06数组指针的编译器内部表示就是有一点特别了。
编译器(或者说是语言本身)有数组指针这个内部表示。
由于c++语言的类型严格检查的语言(当然还有一些是存在隐式类型转化的)
所以我们下面的写法是不能编译通过的。
{
int arr[3]={10,20};//注意是3个元素数组
int (*p2arr)[2]=&arr;//注意是指向2个元素数组的指针
}
小结
关于数组和指针的转化,以及我们使用指针(++,--)等来操作数组,是基于数组在内存中是连续分布的。
看到这里就会明白下面的程序为什么会运行的了。
我这里也把下面的程序作为今天内容的总结:
#include <iostream>
using namespace std;
int main()
{
int a[2]={10,20};
int *p=a;//根据上面说明,由于编译器的参与,两者类型转化后一致
int vInt=10,vInt1=11;
int *parr[2]={&vInt,&vInt1};
int **p2p=parr;//上面分析,类型一致
cout<<*parr[0]<<" "<<*parr[1]<<endl;
cout<<*(*p2p)<<" "<<*(*(p2p+1)) <<endl;
return 0;
}
输出结果 cout<<*parr[0]<<" "<<*parr[1]<<endl; ----------10 11
cout<<*(*p2p)<<" "<<*(*(p2p+1)) <<endl;------10 11
- 指针函数和函数指针有什么区别
- 指针函数和函数指针有什么区别
- 指针函数和函数指针有什么区别(转载)
- 指针函数和函数指针有什么区别
- 指针函数和函数指针有什么区别(转载)
- 指针函数和函数指针有什么区别(转载)
- 指针函数和函数指针有什么区别
- 指针函数和函数指针有什么区别
- 指针函数和函数指针有什么区别
- 指针函数和函数指针有什么区别
- 指针函数和函数指针有什么区别
- 指针函数和函数指针有什么区别
- 指针函数和函数指针有什么区别
- 指针函数和函数指针有什么区别
- C++ 指针函数和函数指针有什么区别
- 指针函数和函数指针有什么区别
- 指针函数和函数指针有什么区别
- block和函数指针有什么区别
- linux /etc/fstab
- offsetLeft,Left,clientLeft的区别
- CGI脚本
- HelloNDK
- ubuntu 12.04 samba 配置
- C++ 指针函数和函数指针有什么区别
- linux常用命令——ps
- Ubuntu12.04配置Hadoop1.1.2集群
- 艺术家书画笔会捐赠30万元援助雅安救灾
- Android 调用堆栈跟踪(二)
- Android 剪裁图片
- Word 常用功能技巧总结
- 数据库连接池dbcp整理
- 限定长度的最大子段和