数组
二维数组的分析(了解)
案例 1:
1 2 3 4 5 6 7 8 9 int arr[3 ][4 ];printf ("%d" ,*(*(arr+1 )+2 ));
二维数组名:代表的是二维数组的首行地址,+1 跳过一行 对行地址取 *
将变成当前行的第 0 列的列地址arr[0]=*(arr+0)=*arr
arr[1]=*(arr+1)
案例 2:说出下面分别代表的是啥?
1 2 3 4 5 6 int arr[3 ][4 ];*arr+2 ; arr[1 ]; &arr[0 ]+2 ; **arr;
数组指针与二维数组的关系
案例 1:定义一个指针变量,保存二维数组的行地址
1 2 3 4 5 6 7 8 9 #include <stdio.h> int main (int argc,char *argv[]) { int arr[3 ][4 ]; int (*p)[4 ]; p=arr; return 0 ; }
案例 2:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #include <stdio.h> int main (int argc,char *argv[]) { int arr[3 ][4 ]={{1 ,2 ,3 ,4 },{5 ,6 ,7 ,8 },{9 ,10 ,11 ,12 }}; int (*p)[4 ]=arr; int i=0 ,j=0 ; printf ("%d\n" ,sizeof (p)); for (i=0 ;i<3 ;i++){ for (j=0 ;j<4 ;j++){ printf ("%d " ,p[i][j]); } printf ("\n" ); } return 0 ; }
运行结果:
任何维度数组,在物理存储上都是一维的
我们可以通过一维来访问多维数组,因为内存条是一维的,地址是连续的
案例 1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #include <stdio.h> int main (int argc,char *argv[]) { int arr[3 ][4 ]={{1 ,2 ,3 ,4 },{5 ,6 ,7 ,8 },{9 ,10 ,11 ,12 }}; int *p=&arr[0 ][0 ]; int i=0 ; for (i=0 ;i<3 *4 ;i++){ printf ("%d " ,*(p+i)); } printf ("\n" ); for (i=0 ;i<3 *4 ;i++){ printf ("%d " ,p[i]); } return 0 ; }
运行结果:
多级指针
1 级指针 保存 0 级指针变量的地址(普通变量) 2 级指针 保存 1 级指针变量的地址 3 级指针 保存 2 级指针变量的地址 ···· n 级指针 保存 n-1 级指针变量的地址
指针作为函数的参数
如果想要在函数内部,修改函数外部变量的值,就需要将函数外部变量的地址,传递给函数(以指针变量作为函数的参数) 【重要重要重要!!!】
一维数组,作为函数的形参会被优化成指针变量
引入:
案例 1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 #include <stdio.h> void my_swap (int a,int b) { printf ("a=%d\n" ,a); printf ("b=%d\n" ,b); int temp=0 ; temp=a; a=b; b=temp; printf ("a=%d\n" ,a); printf ("b=%d\n" ,b); return ; } int main (int argc,char *argv[]) { int data1=4 ,data2=5 ; my_swap(data1,data2); printf ("data1=%d\n" ,data1); printf ("data2=%d\n" ,data2); return 0 ; }
运行结果:
分析:data1,data2
之间的值并未被交换,然而a,b
的值交换成功了;因为当函数调用的时候,系统给形参分配内存空间,通过传参将实参传给了局部变量形参,在函数里面操作的只是形参a,b
;并不是data1,data2
解决方法:要解决上面的问题,就要给函数传入data1,data2
变量的地址
解决方案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 #include <stdio.h> void my_swap (int *a,int *b) { printf ("a=%d\n" ,*a); printf ("b=%d\n" ,*b); int temp=0 ; temp=*a; *a=*b; *b=temp; printf ("a=%d\n" ,*a); printf ("b=%d\n" ,*b); return ; } int main (int argc,char *argv[]) { int data1=4 ,data2=5 ; my_swap(&data1,&data2); printf ("data1=%d\n" ,data1); printf ("data2=%d\n" ,data2); return 0 ; }
运行结果:
分析:交换成功!
案例 2:在函数内部更改 p 的指向
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #include <stdio.h> void my_set (int **tem_p) { static int num=100 ; *tem_p=# } int main (int argc,char *argv[]) { int *p=NULL ; my_set(&p); printf ("%d\n" ,*p); return 0 ; }
一维数组名作为函数的参数
1. 如果函数内部想要操作(读、写)外部数组的元素,请将外部数组的数组名传递给函数
案例 1:为什么同样的数组总大小不一样?
1 2 3 4 5 6 7 8 9 10 #include <stdio.h> void my_input_array (int arr[5 ],int n) { printf ("B:%d\n" ,sizeof (arr)); } int main (int argc,char *argv[]) { int arr[5 ]={0 }; printf ("A:%d\n" ,sizeof (arr)); return 0 ; }
运行结果:
分析:因为系统会自动把void my_input_array(int arr[5],int n){
优化为void my_input_array(int *arr,int n){
,所以B:4
输出的是指针的字节数 4.
一维数组,作为函数的形参会被优化成指针变量
案例 2:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 #include <stdio.h> void my_input_array (int arr[5 ],int n) { int i=0 ; printf ("请输入5个int类型数据:\n" ); for (i=0 ;i<n;i++){ scanf ("%d" ,arr+i); } } void my_printf_array (int arr[5 ],int n) { int i=0 ; for (i=0 ;i<n;i++){ printf ("%d " ,arr[i]); printf ("%d\n" ,*(arr+i)); } } int main (int argc,char *argv[]) { int arr[5 ]={0 }; int n=sizeof (arr)/sizeof (arr[0 ]); my_input_array(arr,n); my_printf_array(arr,n); return 0 ; }
运行结果:
二维数组名作为函数的参数
如果想要在函数内部,修改函数外部变量的值,就需要将函数外部变量的地址,传递给函数(以指针变量作为函数的参数) 【重要重要重要!!!】
二维数组名,作为函数的形参,会被优化成数组指针 1 2 3 4 5 6 7 int arr1[5 ]--->int *p1int arr2[3 ][4 ]--->int (*p2)[4 ]int arr3[3 ][4 ][5 ]--->int (*p3)[4 ][5 ]int arr4[3 ][4 ][5 ][6 ]--->int (*p4)[4 ][5 ][6 ]·········..........·········
案例1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 #include <stdio.h> void my_printf_two_array (int arr[3 ][4 ],int row,int col) { printf ("B:%d\n" ,sizeof (arr)); } int main (int argc,char *argv[]) { int arr[3 ][4 ]={{1 ,2 ,3 ,4 },{5 ,6 ,7 ,8 },{9 ,10 ,11 ,12 }}; int row=sizeof (arr)/sizeof (arr[0 ]); int col=sizeof (arr[0 ])/sizeof (arr[0 ][0 ]); printf ("A:%d\n" ,sizeof (arr)); my_printf_two_array(arr,row,col); return 0 ; }
运行结果:
分析:当二维数组作为函数的参数时,会被优化成数组指针 即,void my_printf_two_array(int arr[3][4],int row,int col){
变成void my_printf_two_array(int (*arr)[4],int row,int col){
案例2:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #include <stdio.h> void my_printf_two_array (int (*arr)[4 ],int row,int col) { int i=0 ,j=0 ; for (i=0 ;i<row;i++){ for (j=0 ;j<col;j++){ printf ("%d " ,arr[i][j]); } printf ("\n" ); } } int main (int argc,char *argv[]) { int arr[3 ][4 ]={{1 ,2 ,3 ,4 },{5 ,6 ,7 ,8 },{9 ,10 ,11 ,12 }}; int row=sizeof (arr)/sizeof (arr[0 ]); int col=sizeof (arr[0 ])/sizeof (arr[0 ][0 ]); my_printf_two_array(arr,row,col); return 0 ; }
运行结果:
指针作为函数的返回值
案例2:
1 2 3 4 5 6 7 8 9 10 11 12 13 #include <stdio.h> int * get_addr (void ) { static int num=1000 ; return # } int main (int argc,char *argv[]) { int *p=NULL ; p=get_addr(); printf ("%d\n" ,*p); return 0 ; }
运行结果:
函数名,代表的是函数的入口地址
案例1:
1 2 3 4 5 6 7 8 #include <stdio.h> int my_add (int a,int b) { return a+b; } int main (int argc,char *argv[]) { printf ("%p\n" ,my_add); return 0 ; }
运行结果:
案例2:定义一个指针变量,保存函数的入口地址
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 #include <stdio.h> int my_add (int a,int b) { return a+b; } int main (int argc,char *argv[]) { int (*p)(int ,int )=NULL ; p=my_add; printf ("my_add=%p\n" ,my_add); printf ("p=%p\n" ,p); printf ("%d\n" ,my_add(10 ,20 )); printf ("%d\n" ,p(30 ,40 )); printf ("%d\n" ,(*p)(30 ,40 )); (*******printf )("hello\n" ); return 0 ; }
运行结果:
指针函数的应用-函数指针作为函数的形参
案例1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 #include <stdio.h> int my_add (int a,int b) { return a+b; } int my_sub (int a,int b) { return a-b; } int my_mul (int a,int b) { return a*b; } int my_calc (int a,int b,int (*fun_pointer)(int ,int )) { return fun_pointer(a,b); } int main (int argc,char *argv[]) { printf ("%d\n" ,my_calc(10 ,20 ,my_add)); printf ("%d\n" ,my_calc(10 ,20 ,my_sub)); printf ("%d\n" ,my_calc(10 ,20 ,my_mul)); return 0 ; }
运行结果: