C语言第14天,指针作为参数传递、多级指针和指针数组

一、指针作为参数传递

1.为什么需要指针作为参数传递?

因为实参与形参相互独立,被调函数无法影响主调函数中的变量

#include<stdio.h>

 

void swap(int x,int y)

{int temp=x; x=y; y=temp;}

 

int main()

{int a,b;  int temp; 

a=1; b=2;

printf("a=%d b=%d\n",a,b);

//交换a,b变量

swap(a,b);

printf("a=%d b=%d\n",a,b);

return 0;}

 

由于主调函数的变量a,b与被调函数的形参x,y它们相互独立。函数swap可以修改变量x,y,但是却无法影响到主调函数中的a,b。

在被调函数内部无法直接修改主调函数的变量,那么我们采用迂回战术,

在函数main中取得a、b的指针。将两个指针传递到函数swap。那么,在函数swap内部可以根据这两个信息修改a、b。

 

#include<stdio.h>

 

void swap(int *x,int *y)

{int temp=*x; *x=*y; *y=temp;}

 

int main()

{int a,b;  int temp; 

a=1; b=2;

printf("a=%d b=%d\n",a,b);

//交换a,b变量

swap(&a,&b);

printf("a=%d b=%d\n",a,b);

return 0;}

 

结果为a=1 b=2

a=2 b=1


将x,y改为了int*类型的指针。在主调函数中,对a,b进行取地址获取指针并传入函数swap。在函数swap内部,通过这两个指针交换目标数据对象的值。

注意,不是交换指针x,y的值,而是交换目标数据对象a,b的值。所以,需要在指针前使用取值运算符*。

 

2.仅有首地址的指针类型void*

若要用函数swap交换两个int类型的变量,必须传入指向这两个int类型变量的指针。函数内部可以通过指针知道对象的首地址和类型。

但是,这样也使得函数swap,只能交换int类型的变量了。那么如何让函数swap函数更加通用一点,可以交换更多类型的变量呢?

 

 int*修改为void*。类型为void*的指针仅保存首地址,不保存目标数据对象的空间大小。

所以,不能对void*类型的指针进行取值。同样的,它也没有步长,所以不能对void*类型的指针进行加减运算。

但是,void*有一个好处,那就是任意类型的指针都可以直接赋值给它。而其他类型的指针是不能相互赋值的,由于赋值会改变目标数据对象的类型。

void swap(void *x,void *y,int size)

{//指针转为char*,单个字节操作内存

char *pX=(char*)x;

char *pY=(char*)y;

char temp;

 

for(int i=0;i<size;i++)

{temp=pX[i];

pX[i]=pY[i];

pY[i]=temp;}

}

 

二、多级指针

二级指针:int*的指针的类型为int**

#include<stdio.h>

int main()

{int n=123;

int*pn=&n;

int**pnn=&pn;

printf("**pnn=%d\n",**pnn);

return 0;}

 

过程:1.对pnn使用取值运算符,将int**还原为int*。

2.对*pnn使用取值运算符,将int*还原为int。即,还原为n。

结果为n=123

 

三、指针数组

int arr1[5]={1,2,3,4,5};
int arr2[5]={11,22,33,44,55};
int arr3[5]={111,222,333,444,555};
 
若数组名出现在表达式中,即会转换为指向首元素的指针,即int*类型。
 
int*pToArr[3];
pToArr[0]=arr1;//arr1转换为首元素指针,int[5]到int*
pToArr[1]=arr2;//arr2转换为首元素指针,int[5]到int*
pToArr[2]=arr3;//arr3转换为首元素指针,int[5]到int*
 
pToArr的类型为int*[3],是一个数组。它有3个元素,每个元素的类型为int*。由于元素类型为指针,所有它也被称为指针数组
定义和赋值完数组后,我们使用这个指针数组来访问所有元素
 
for(int i=0 ;i<3; i++)
int**p=pToArr+i;//p,指向pToArr的第一个元素arr1,类型为int**。
for(int j=0; j<5; j++)
printf("%d",*(*p+j));
printf("\n");}
 
*p,指向arr1的第一个元素,类型为int*。
*p+j,指向arr1中的第j个元素,类型为int*。
*(*p+j),为arr1中的第j个元素。
 
四、从函数中返回指针
#include<stdio.h>
int*func()
{
int n=100;
return&n;
}
int main()
{
int*p=func();
printf("%d\n",*p);
return 0;
}
 
在函数func中定义了变量n。接着,return&n取得变量n的指针,并返回到main函数。main函数收到返回值后赋值给p,并使用指针p来访问变量n。
结果为100
但因为函数与函数之间的变量是独立的,即使是同一个函数多次运行,这些变量也是独立的。在函数返回后,函数内的变量没有继续存在的意义了。
所以,函数内的变量将被回收,回收后的内存空间将给接下来运行的函数使用。当我们需要重复使用函数时,需要用到static函
 

 

static 关键词static让变量n不被回收

int*func()
{
static int n=100;//关键词static让变量n不被回收
n++;
return&n;
}

#include<stdio.h>
int main()
{
int*p=func();
printf("%d\n",*p);
func();
printf("%d\n",*p);
func();
printf("%d\n",*p);
func();
printf("%d\n",*p);
func();
printf("%d\n",*p);
return 0;
}

结果为

101
102
103
104
105

如果没有static那么n丢失,结果都为101

 

五、从函数中返回多个变量

void func(int** a,int** b)
{
static int x=100;
static int y=200;
*a=&x;
*b=&y;
}
#include<stdio.h>
int main()
{//两个指针,初始化为空
int* c=NULL;//null将变量的首地址设为0
int* d=NULL;
func(&c,&d);//将指针的指针传入被调函数
if(c!=NULL&&d!=NULL)
printf("c=%d d= % d\n",* c,*d);
return 0;
}

函数func内部,&x、&y取得变量x、y的指针,类型为int*。在被调函数内,为了修改主调函数中的变量,先对二级指针a、b取值,将int**转换为int*,再赋值一个int给它

posted @ 2022-09-21 11:36  纯爱暴打ntr  阅读(461)  评论(0)    收藏  举报