1、数组与指针,函数封装
数组名即为地址(指针)
#include <stdio.h>
void initArray(int *parr,int size)//*为标记作用
{
int i;
for(i =0;i<size;i++)
{
printf("请输入第%d个元素的数据:\n",i+1);
scanf("%d",parr++);
}
}
void printArray(int *parr,int size)//*为标记作用
{
int i;
for(i =0;i<size;i++)
{
printf("%d",*parr++);//*为取值作用
}
}
int main()
{
int arry[5];
int size = sizeof(arry)/sizeof(arry[0]);
initArray(arry,size);
printArray(&arry[0],size);//实际参数:数组的首地址/数组名/首个元素的地址
return 0;
}
2、数组翻转函数封装
#include <stdio.h>
void initArray(int *parr,int size)//*为标记作用
{
int i;
for(i =0;i<size;i++)
{
printf("请输入第%d个元素的数据:\n",i+1);
scanf("%d",parr++);
}
}
void revangeArry(int *parr,int size)
{
int i,j;
int temp;
for(i = 0;i<size/2;i++)
{
j = size-1-i;
temp = parr[i]; //temp = *(parr+i); 地址偏移,paar为数组首元素的地址
parr[i] = parr[j]; //*(parr+i) = *(parr+j); 这几行*为取值作用
parr[j] = temp; //*(parr+j) = temp;
}
}
void printArray(int *parr,int size)//*为标记作用
{
int i;
for(i =0;i<size;i++)
{
printf("%d",*parr++);//*为取值作用
}
}
int main()
{
int arry[5];
int size = sizeof(arry)/sizeof(arry[0]);
initArray(arry,size);
printArray(&arry[0],size);//实际参数:数组的首地址/数组名/首个元素的地址
revangeArry(&arry[0],size);
printArray(&arry[0],size);
return 0;
}
3、二维数组地址(指针)
父子数组
int a[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};
a是二维数组名,父数组的名,父数组的地址————行
子数组的名(地址):a[0]、a[1]、a[2]————————列
问:a+1偏移了多少?a[0]+1偏移了多少?
答:a+1从1到5,16个字节
a[0]+1从1到2;4个字节
!!!数组名也是数组首元素地址
对于二维数组,a[1](子数组的名)=&a[1][0](子数组的第一个元素取地址)
a[2]=&a[2][0]
首地址:①数组名;②首个元素的地址;
*a = a[0] *(a+1) = a[1] //此处*为取值作用
实例:
①
#include <stdio.h>
int main()
{
int arr[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};
printf("arr是父数组地址:%p,偏移1后为:%p\n",arr,arr+1);
printf("arr[0]是子数组地址:%p,偏移后1为:%p\n",arr[0],arr[0]+1);
printf("arr[0]是子数组地址:%p,偏移1后为:%p\n",*(arr+0),*(arr+0)+1);//对二维数组的第一个元素取值即为{1,2,3,4},也就是该元素的地址
}
运行结果:
arr是父数组地址:000000000061FDF0,偏移1后为:000000000061FE00
arr[0]是子数组地址:000000000061FDF0,偏移后1为:000000000061FDF4
arr[0]是子数组地址:000000000061FDF0,偏移1后为:000000000061FDF4
②、遍历数组
#include <stdio.h>
int main()
{
int arr[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};
int i;
int j;
for(i=0;i<3;i++)
{
for(j=0;j<4;j++)
{
printf("地址:%p;数据:%d\n",&arr[i][j],arr[i][j]);
printf("地址:%p;数据:%d\n",arr[i]+j,*(arr[i]+j));
printf("地址:%p;数据:%d\n",*(arr+i)+j,*(*(arr+i)+j));
printf("=============\n");
}
printf("\n");
}
}
运行结果:
地址:000000000061FDE0;数据:1
地址:000000000061FDE0;数据:1
地址:000000000061FDE0;数据:1
=============
地址:000000000061FDE4;数据:2
地址:000000000061FDE4;数据:2
地址:000000000061FDE4;数据:2
=============
地址:000000000061FDE8;数据:3
地址:000000000061FDE8;数据:3
地址:000000000061FDE8;数据:3
=============
地址:000000000061FDEC;数据:4
地址:000000000061FDEC;数据:4
地址:000000000061FDEC;数据:4
=============
地址:000000000061FDF0;数据:5
地址:000000000061FDF0;数据:5
地址:000000000061FDF0;数据:5
=============
地址:000000000061FDF4;数据:6
地址:000000000061FDF4;数据:6
地址:000000000061FDF4;数据:6
=============
地址:000000000061FDF8;数据:7
地址:000000000061FDF8;数据:7
地址:000000000061FDF8;数据:7
=============
地址:000000000061FDFC;数据:8
地址:000000000061FDFC;数据:8
地址:000000000061FDFC;数据:8
=============
地址:000000000061FE00;数据:9
地址:000000000061FE00;数据:9
地址:000000000061FE00;数据:9
=============
地址:000000000061FE04;数据:10
地址:000000000061FE04;数据:10
地址:000000000061FE04;数据:10
=============
地址:000000000061FE08;数据:11
地址:000000000061FE08;数据:11
地址:000000000061FE08;数据:11
=============
地址:000000000061FE0C;数据:12
地址:000000000061FE0C;数据:12
地址:000000000061FE0C;数据:12
=============
总结:
二维数组a的有关指针
表示形式 含义 a 二维数组名,指向一维数组a[0],即0行首地址 a[0],*(a+0),*a 0行0列元素地址 a+1,&a[1] 1行首地址 a[1],*(a+1) 1行0列元素a[1][0]的地址 a[1]+2,*(a+1)+2,&a[1][2] 1行2列元素a[1][2]的地址 *(a[1]+2),*(*(a+1)+2),a[1][2] 1行2列元素a[1][2]的值
4、数组指针
定义一个指针,指向一个数组
数组指针真正意义上等同于二维数组名
也就是说定义一个指针,就是子数组的地址
格式:
int arr[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};
int(*p)[4];
p = arr;
//数组指针遍历数组
#include <stdio.h>
int main()
{
int arr[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};
int i;
int j;
int (*p)[4];
p = arr;
for(i=0;i<3;i++)
{
for(j=0;j<4;j++)
{
printf("%d\n",*(*(p+i)+j));
}
}
}
练习:二维数组,输入行列,取值
//二维数组,输入行列,取值
#include <stdio.h>
int findResult(int (*p)[5],int hang,int lie)
{
int data;
data = *(*(p+hang)+lie);
return data;
//return p[hang][lie];
}
void tipsInputHangLie(int *pm,int *pn)
{
printf("请输入行列值:");
scanf("%d%d",pm,pn);
puts("输入完成!");
}
int main()
{
int arr[3][5] = {{1,2,3,4,1},{5,6,7,8,1},{9,10,11,12,1}};
int ihang,ilie;
int data;
//1、提示用户输入行列值
tipsInputHangLie(&ihang,&ilie);
//2、找出对应的那个数
data = findResult(arr,ihang,ilie);
//3、打印出来
printf("第%d行第%d列的数为%d\n",ihang,ilie,data);
}
5、函数指针
函数地址:如果在程序中定义了一个函数,在编译时,编译系统为函数代码分配了一段存储空间,这段存储空间的起始地址(又称入口地址)称为这个函数的指针。
函数名即为地址。
如何定义一个函数指针变量? int a —— int *p char c —— char *p int getData(int a,int b) —— int(*p)(int a,int b)
使用函数指针
//函数指针
#include <stdio.h>
int inDate(int data)
{
return ++data;
}
void printWelcome()
{
puts("欢迎!");
}
int main()
{
//定义函数指针
void(*p1)();
int(*p2)(int data);
//指向函数
p1 = printWelcome;
p2 = inDate;
//调用
(*p1)();
printf("p2测试:%d\n",(*p2)(10));
return 0;
}
练习:有两个整数a和b,由用户输入1,2或3。如输入1,程序给出最大者,输入2,给出最小者,输入3,求ab之和。
//有两个整数a和b,由用户输入1,2或3。
//如输入1,程序给出最大者,
//输入2,给出最小者,
//输入3,求ab之和。
#include <stdio.h>
int getMax(int data1,int data2)
{
return data1>data2?data1:data2;
}
int getMin(int data1,int data2)
{
return data1>data2?data2:data1;
}
int getSum(int data1,int data2)
{
return data1+data2;
}
int dataHand(int data1,int data2,int (*pfunc)(int data1,int data2))
{
int result;
result = (*pfunc)(data1,data2);
return result;
}
int main()
{
int a = 1;
int b = 2;
int cmd;
int result;
//函数指针
int (*pfunc)(int data1,int data2);
printf("请输入:");
scanf("%d",&cmd);
switch(cmd)
{
case 1:
pfunc = getMax;
break;
case 2:
pfunc = getMin;
break;
case 3:
pfunc = getSum;
break;
default:
printf("输入错误!");
}
result = dataHand(a,b,pfunc);
printf("result = %d\n",result);
return 0;
}
6、指针数组
int *p[4];
是一个数组,数组的每一项都是一个指针变量
#include <stdio.h>
int main()
{
int a = 1;
int b = 2;
int c = 3;
int d = 4;
int *p[4] = {&a,&b,&c,&d};//标识
for(int i = 0;i<4;i++)
{
printf("%d ",*(p[i]));//p[i]是一个地址,对地址取值
}
return 0;
}
函数指针数组
//有两个整数a和b,求最大者、最小者、ab之和。
#include <stdio.h>
int getMax(int data1,int data2)
{
return data1>data2?data1:data2;
}
int getMin(int data1,int data2)
{
return data1>data2?data2:data1;
}
int getSum(int data1,int data2)
{
return data1+data2;
}
int main()
{
int a = 1;
int b = 2;
int result;
//函数指针数组
int (*pfunc[3])(int ,int ) = {getMax,getMin,getSum};
for(int i=0;i<3;i++)
{
result = (*pfunc[i])(a,b);
printf("result = %d\n",result);
}
return 0;
}
7、指针函数
函数的返回值为指针类型即地址
8、二级指针
#include <stdio.h>
int main()
{
int data = 3;
printf("data的地址为:%p\n",&data);
int *p1 = &data;
printf("p1保存data的地址为%p,数据是%d\n",p1,*p1);
int **p2 = &p1;
printf("p2保存p1的地址为%p,数据是%d\n",p2,**p2);
}
9、总结
各种指针的定义
①一个整型数:int a;
②一个指向整型数的指针:int *a; (指针)
③一个指向指针的指针,它指向的指针指向一个整型数:int **a; (二级指针)
④一个有10个整型数的数组:int a[10]; (数组 )
⑤一个有10个指针的数组,每个指针指向一个整型数:int *a[10];(指针数组)
⑥一个指向有10个整型数的数组的指针:int (*a)[10];(数组指针,数组每一项为整型数)
⑦一个指向指针的指针,被指向的指针指向一个有10个整型数的数组:int (**a)[10];
⑧一个指向指针的指针,该数组有10个整型指针:int *(*a)[10](数组指针,数组每一项为整型指针)
⑨一个指向函数的指针,该函数有一个整型参数并返回一个整型数:int (*a)(int);(函数指针)
⑩一个有10个指针的数组,每个指针指向一个函数,该函数有一个整型参数并返回一个整型数:int (*a[10])(int); (函数指针数组,是一个数组)
⑪一个函数的指针,指向的函数的类型是有两个整型参数并且返回一个函数只针对函数,返回的函数指针指向有一个整型参数且返回整型数的函数:int(*(*a)(int,int))(int);