初探:
对于初学指针的小伙伴来说提起指针就已经够头疼的了,那如果在代码中遇到指针函数、函数指针、指针数组、数组指针....指针家族都一块来了,更是连看下去的勇气都没有了,不要急,c语言灵活的地方就在指针上面,指针是c语言的灵魂,这篇文先让你了解一下概念,分清这几种指针家族的本质,在实际过程中多用才能有更深的体会。
首先实体是什么先要分清楚,在前两个字与后两个字的中间加上一个 ‘的’ 会好很多。
指针函数不就是有指针的函数,实体是函数,这个函数的返回值类型是指针
函数指针不就是拥有函数的指针,实体是指针,这个指针拥有函数,也就是这个指针指向函数
指针数组不就是有指针的数组,实体是数组,这个数组里面装着指针
数组指针不就是拥有数组的指针,实体是指针,这个指针指向数组
这样一分析后,是不是就清晰很多?下面让我们做一下具体分析
指针函数:
函数体内该怎么写还是怎么去写,只不过最后返回的是一个指针类型。这面这个例子是计算a+b的值,返回一个指针类型。下面这个代码有坑!
int *sum(int a, int b)
{
int c;
/*int *p;
p = &c;*/
c = a + b;
return &c;
}
int main()
{
int *p;
int a, b;
a = 3; b = 2;
p = sum(a, b);
//cout << endl;
cout << a << " + " << b << " = " << *p << endl;
}
我先面说这个代码有坑,但是运行后发现没有问题啊,输出很正常,但如果延时一下,把那个main函数中的注释去掉,就会出问题了,有的编译器会出现一行警告:warning C4172: 返回局部变量或临时变量的地址,原因何在呢?就是因为我们在函数中定义的c是一个临时变量,存放在栈区,这个子函数一结束就会被释放掉,没有延时的直接输出出现正确情况可能只是一种巧合,那一块区域还没被释放掉,但你过一会再去访问就会出错。避免这种错误出现的方法是,只需让c这个变量在子函数运行后不被释放掉就可以了,用静态变量static就可以。下面是正确的代码
int *sum(int a, int b)
{
static int c;
/*int *p;
p = &c;*/
c = a + b;
return &c;
}
函数指针:
一般形式: 返回值类型 (*指针名)(参数); 如果我们用函数指针不得不考虑函数重载的问题
重载
int sum(int a, int b)
{
int c;
/*int *p;
p = &c;*/
c = a + b;
return c;
}
void sum()
{
cout << "sum的重载" << endl;
}
int main()
{
int (*p)(int,int); //下面这两种格式也可以
//int(*p)(); //有重载的情况不适合用这种形式
//int(*p)(int a, int b);
int a, b,c;
a = 3; b = 2;
p = sum;
c = p(a,b); //下面这种格式也可以
//c = (*p)(a, b);
cout << a << " + " << b << " = " << c << endl;
//重载
void (*pf)();
pf = sum;
pf();
}
回调:
把一个函数的指针作为参数传递到另一个函数的参数中
int sum(int a, int b)
{
int c;
/*int *p;
p = &c;*/
c = a + b;
return c;
}
void function(int(*p)(int, int))
{
int a, b, c;
a = 3; b = 2;
cout << "这是在function中调用其他函数" << endl;
c = p(a, b);
cout << a << " + " << b << " = " << c << endl;
}
int main()
{
function(sum);
}
typedef:
如果程序中有比较多的函数指针,那么没定义一个变量就要写一遍这个类型,不仅麻烦还容易出错,所以用typedef为他定义一个简短的名字就很有必要。
typedef int(*PFON)(int, int);
int sum(int a, int b)
{
int c;
/*int *p;
p = &c;*/
c = a + b;
return c;
}
int main()
{
int a, b,c;
a = 3; b = 2;
PFON pfon;
pfon = sum;
c = pfon(a, b);
cout << a << " + " << b << " = " << c << endl;
}
指针数组:
首先,与要明确这几个符号的优先级问题:()= [] > * ,优先级相同从左到右,根据这个优先级关系推出 int * parray[4] 是一个指针数组
int *sum(int a, int b)
{
static int c;
/*int *p;
p = &c;*/
c = a + b;
return &c;
}
int main()
{
int * parray[3];
int a=2, b=3;
parray[0] = &a;
parray[1] = &b;
parray[2] = sum(*parray[0], *parray[1]); //此函数返回的直接是指针类型
cout << *parray[0] << " + " << *parray[1] << " = " << *parray[2] << endl;
}
数组指针:
首先我们要知道指向数组的指针与指向数组首元素的指针是两码事!!!
int main()
{
int array[3] = { 1, 2, 3 };
int *p1 = array; //指向数组的指针
int (*p2)[3];
p2 = &array; //指向数组首地址的指针,需要二次解引用
for (int i = 0; i < 3; i++)
{
cout << *(*p2+i) << " "; //*p2相当于array
}
}