C/C++学习——指针与函数

指针作为函数的参数

一、一般定义形式为:
返回类型 函数名(指向类型 *指针变量名)
{
函数体
}

#include 
using namespace std;

void swap(int *p1, int *p2)
{
	int temp;
	temp = *p1;
	*p1 = *p2;
	*p2 = temp;
}
int main()
{
	int a, b;
	cin >> a >> b;
	if (a > b)
	{
		swap(&a, &b);
	}

	cout <<"min:" <<a <<"max:" <<b << endl;

}

2、通过将指针作为函数参数的方法,即可以返回多个运算结果,又避免使用了全局变量。

示例;
计算a和b的平方和,自然对数和,几何平均数,和的平方根。

#include 
#include 
using namespace std;

void  fun(double x,double y,double *fsq,double *fln,double *favg,double *fsqr)
{
	*fsq = x * x + y * y;
	*fln = log(x) + log(y);
	*favg = (x + y) / 2;
	*fsqr = sqrt(x + y);
}
int main()
{
	double a = 10, b = 13, fsq, fln, favg, fsqr;
	fun(a,b,&fsq,&fln,&favg,&fsqr);
	cout << a << "," << b << "," << fsq << "," << fln << "," << favg << "," << fsqr << endl;
	return 0;
}

数组作为函数的参数

一、定义形式

double average(double *a,int n)
{
	函数体
}
函数调用形式如下:
double X[100],f;
f=average(X,100);

示例:求数组的平均值

#include 
using namespace std;

double average(int *A, int n)
{
	double aver;
	int *p = A,sum=0;
	for (p = A; p < A + n; p++) sum = sum + *p;
	return n<0? 0:aver = sum / n;
}
int main()
{
	int A[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int aver = average(A, 10);
	cout << aver << endl;
	return 0;
}

二、
1、想要在子函数中改变主调函数中数组的元素,实参和形参的对应关系有一下四种:
(1)形参和实参都用数组名

void fun(int x[100],int n);//函数原型
int a[100];
fun(a,100);//函数调用

(2)形参用指针变量,实参用数组名

void fun(int *x,int n);//函数原型
int a[100];
fun(a,100);//函数调用

(3) 形参和实参都是用指针变量,

void fun(int *x,int n);//函数原型
int a[100],*p=a;
fun(p,100);//函数调用

(4)形参用数组,实参用指针变量

void fun(int x[100],int n);//函数原型
int a[100],*p=a;
fun(p,100);//函数调用

字符指针变量作为函数形参

将一个字符串传递到函数中,传递的是地址,则函数形参既可以用字符数组,又可以用指针变量,两种形式完全等价。在子函数中可以修改字符串的内容,主调 函数得到的是变化后的字符串。

经典示例一:
自定义函数实现strcpy函数的字符串复制功能

#include 
using namespace std;

char *stringcpy(char *strDest, const char *strSrc)
{
	char *p1 = strDest;
	const char *p2 = strSrc;
	while (*p2 != '\0')
	{
		*p1 = *p2;
		p1++;
		p2++;
	}
	*p1 = '\0';
	return strDest;
}
int main()
{
	char s1[80], s2[80], s3[80] = "string=";
	cin >> s1;//输入字符串
	stringcpy(s2, s1);
	cout << "s2:" << s2 << endl;
	stringcpy(&s3[7], s1);//复制s1到s3的后面
	cout << "s3:" << s3 << endl;
	return 0;
}

引用

  • 通过对象名称直接访问对象,优点是直观,操作哪个对象一目了然,缺点一个函数内部不能使用另一个函数的局部变量
  • 通过指针(或地址)间接访问对象,有点是无所不能,缺点是程序中大量出现的间接访问,是在分不清是哪个对象,需要通过上下文去分析。
  • C++扩充了C语言对象访问方式,提供了引用访问,通过引用访问对象,结合了按命名访问和按地址访问各自的优点,非常适合作为函数参数
    一、引用作为函数参数
    1、引用就是一个对象的别名,命名形式;
    引用类型 &引用名称=对象名称;
int x;//定义整形变量x;
int &r=x;//声明r是x的引用

在c++中,引用全部是const类型,声明后不可更改(即不能在是别的对象的引用)。
2、引用规则
(1)声明一个引用类型变量时,必须同时初始化它,声明它时哪个对象的别名,即绑定对象。
(2)不能有空引用,引用必须与有效对象的内存单元关联。
(3)引用一旦被初始化,就不能改变引用关系,不能在作为其他对象的引用
(4)指定类型的引用不能初始化到其他类型的对象上。
(5)引用初始化与对引用赋值含义完全不同,

int x;
int r=&x;//初始化
r=100;//引用赋值

(6)取一个引用的地址和一个对象的地址完全一样,都是用取地址运算。

int x,&r=x;
int *p1=&x;//p1指向x
int *p2=&r;//p2指向r,本质指向x

引用作为函数的参数

一、C++之所以扩充引用类型,主要是把它作为函数形参,使得C++中给一个函数传递参数有三种方法:

  1. 传递对象本身
  2. 传递指向对象的指针
  3. 传递对象的引用
    示例:变量、指针、引用作为函数参数比较
//传递对象本身
#include 
using namespace std;
//对象作为函数形参
void swap(int a, int b)
{
	int t;
	t = a;
	a = b;
	b = t;
}
int main()
{
	int x = 20, y = 10;
	swap(x, y);
	cout << x << "," << y << endl;//,值不发生改变20   10
	return 0;
}
//传递对象的指针
#include 
using namespace std;
//指针作为函数形参
void swap(int *a, int *b)
{
	int t;
	t = *a;
	*a = *b;
	*b = t;
}
int main()
{
	int x = 10, y = 20;
	swap(&x, &y);
	cout << x << "," << y << endl;//20  10
	return 0;
}
//传递对象的引用
#include 
using namespace std;
//引用作为函数形参
void swap(int &a, int &b)
{
	int t;
	t = a;
	a = b;
	b = t;
}
int main()
{
	int x = 10, y = 20;
	swap(x, y);
	cout << x << "," << y << endl;//20  10
	return 0;
}

使用引用作为函数形参,比使用指针变量简单、直观、方便,特别是避免了在被调函数中出现大量指针间接访问时,所指对象究竟是哪个具体对象伤脑筋的问题,从而降低了编程的难度。

引用作为函数返回值

引用的返回值可以是引用类型,即函数返回引用,其定义形式为:
引用类型& 函数名(形式参数列表)
{
函数体、
}

//函数返回值
#include 
using namespace std;

int max(int a, int b)
{
	return (a > b ? a : b);
}
int main()
{
	int x = 10, y = 20,z;
	z = max(x, y);
	cout << z << endl;
	return 0;
}
//函数返回指针
#include 
using namespace std;

int* max(int a, int b)
{
	return (a > b ? &a : &b);
}
int main()
{
	int x = 10, y = 20,*z;
	z = max(x, y);//z为地址
	cout << *z << endl;
	return 0;
}
//函数返回引用
#include 
using namespace std;

int& max(int &a, int &b)
{
	return (a > b ? a : b);
}
int main()
{
	int x = 10, y = 20,z;
	z = max(x, y);
	cout << z << endl;
	return 0;
}

可以看出,函数返回引用与函数返回值有重大区别,它不是返回一个临时对象,而是相当于返回实体对象本身。正因为如此,函数返回引用可以作为左值。

int& fun(int &a,int &b)
{	
	return (a>b?a:b);
}
int x=10,y=20,z=5;
fun(x,y)=z;//调用fun函数后相当于y=5;
cout<<y;

指向函数的指针

函数是实现特定功能的程序代码的集合,实际上,函数代码在内存中也要占据一段存储空间(代码区内),这段存储空间的起始地址称为函数入口地址。C++规定函数入口地址为函数的指针,即函数名既代表函数,又是函数的指针(或地址)
一、C++允许定义指向函数的指针变量,定义形式为:
返回类型 (*函数指针变量名)(形参列表);
它可以指向如下形式的函数
返回类型 函数名(形式参数列表)
{
函数体
}

int  (*p)(int a,int b);//定义函数指针变量

二、使函数指针指向函数

  • 可以将函数的地址赋值给函数指针变量,形式为:
    函数指针变量=函数名;

  • 它要求函数指针变量与指向函数必须有相同的返回类型,参数个数,参数类型。

int max(int a,int b);
int min(int a, int b);
int (*p)(int a,int b);

则p=max;
称p指向函数max。它也可以指向函数min,即可以指向所有与他有相同的返回类型,参数个数,参数类型的函数。

三、通过函数指针调用函数

  • 对函数指针间接引用即是通过函数指针调用函数,一般形式为:
    函数指针(实参列表)
  • 通过函数指针调用函数,在实参、参数传递、返回值等方面与函数名调用相同,
c=p(a,b);//等价于c=max(a,b)

四、函数指针的用途
指向函数的指针多用于指向不同的函数,从而可以利用指针变量调用不同函数,相当于将函数调用由静态方式(固定地调用指定函数)变为动态方式(调用哪个函数是由指针值来确定)。熟练掌握函数指针的应用,有利于程序的模块化设计,提高程序的可扩展性。
示例:
求定积分
C/C++学习——指针与函数_第1张图片C/C++学习——指针与函数_第2张图片

#include 
#include 
using namespace std;

double integral(double a, double b, double(*f)(double x))
{
	int n = 10000, i;
	double h, x, s = 0.0;
	h = (b - a) / n;
	for (i = 1; i <= n; i++)
	{
		x = a + (i - 1)*h;
		s = s + (f(x) + f(x + h))*h / 2;
	}
	return s;
}

double f1(double x)
{
	return x + 1;
}
double f2(double x)
{
	return exp(-(x*x) / 2);
}
double f3(double x)
{
	return x * x*x;
}
int main()
{
	double a, b;
	cin >> a >> b;
	cout << (integral(a, b, f1) + integral(a, b, f2) + integral(a, b, f3)) << endl;
	return 0;
}

你可能感兴趣的:(c++学习笔记,c++)