1、数组与指针的结合使用
数组名是数组首地址,是一个指针常量,如 int a[10],关系上:a == &a[0],对于二维数组,也有类似的关系,如 int a[2][4],其中 &a[0][0] 、 a 、 &a[0] 、a[0] 在数值上是相等的,都表示首地址,在关系上:a==&a[0] ;a[0]=&a[0][0] ;a[1]=&a[1][0];可参考下面代码的执行结果:
#include<stdio.h>
int main(void)
{
int a[2][4];
printf("%p\n",a);
printf("%p\n",a[0]);
printf("%p\n",&a[0]);
printf("%p\n",&a[0][0]);
return 0;
}
./test
0x7fff647ba190
0x7fff647ba190
0x7fff647ba190
0x7fff647ba190
然后再来看一段代码:
#include <stdio.h>
int main(void) {
int a[10]={1,2,3,4,5,6,7,8,9,0};
int *p=a;
printf("%d\n",a[5]);
printf("%d\n",p[5]);
printf("%d\n",*(a+5)); //*(a++) 错误
printf("%d\n",*(p++)); //p++次改的指针p的值 p+1只是使用了指针并没有修改指针
printf("%d\n",*(p+1));
return 0; }
执行:
./test
6
6
6
1
3
在代码中,p存放的是一维数组 a[10] 的首地址,按照执行逻辑来推算结果:重点看后两行,*(p++),按照运算,应该是先进行取值p,即 *p,所以 *(p++)等于1,之后再执行自加,p存储的地址自加后得到的应该是a[2]的地址,所以 *(p+1)= *(&a[2]+1)= *( &a[3] ) = a[3]。
再看二维数组与指针,参考下面这段代码
#include <stdio.h>
int main(void)
{
int a[2][4]={1,2,3,4,5,6,7,8};
int (*p)[4];
p=a;
printf("%d\n",a[1][2]);
printf("%d\n",p[1][2]);
printf("%d\n",*(*(a+1)+2));
printf("%d\n",*(*(p+1)+2));
return 0;
}
执行:
./test
7
7
7
7
首先分析(*p)[4] 是什么,按照运算符优先级,()与[ ] 都是一级运算符,但遵循从左到右的运算顺序,所以(*p)[4] 代表的是数组指针,本质上是一个指针,指向的是int [4]类型,即一维数组的地址,然而二维数组本质上是由两个一维数组组成的,所以该数组指针保存的的应该是第一个一维数组的首地址,即&a[0][0],另外,在二维数组中,a=&a[0]、a[0]=&a[0][0],所以由此:
*( *(p+1)+2)= * ( * (&a[0]+1)+2) = * (&a[1]+2) = * (&a[1][0]+2)=a[1][2],同时进行总结
int (*p)[4]=a; //数组指针 :本质上是一个指针,保存int [4]类型(即一维数组类型)的地址.
int * p[4]; //指针数组 :本质上是一个数组,数组有4个成员,这4个成员都是int *
--------------------------------------------分割线--------------------------------------------------------------------------
2、指针与函数的结合使用
大部分是指针作为函数的形参,用于址传递
址传递:传地址 修改形参能改变对应实参
#include <stdio.h>
void swap(int *a,int *b)
{
int temp;
temp=*a;
*a=*b;
*b=temp;
}
int main(void)
{
int a,b;
scanf("%d%d",&a,&b);
swap(&a,&b);
printf("%d %d\n",a,b);
return 0;
}
执行:
./test
输入:1 2
输出:2 1
值传递:传数值 修改形参不能改变对应实参
#include <stdio.h>
void fun(int *p)
{
int b=20;
p=&b;
*p=50;
}
int main(void)
{
int a=10;
fun(&a);
printf("%d\n",a);
return 0;
}
执行:
./test
输入:10
输出:10
再看一个例子
例:封装函数,求两个数的和与差
#include <stdio.h>
void fun(int c,int d,int *p,int *q) //因为指针做形参,修改形参的值能够改变实参的值 利用这个特点,实现函数把多个数据传出去
{
*p=c+d;
*q=c-d;
}
int main(void)
{
int a,b;
scanf("%d%d",&a,&b);
int sum,sub;
fun(a,b,&sum,&sub);
printf("%d %d\n",sum,sub);
return 0;
}
数组与函数的结合:
把数组传到自定义函数中进行操作。数组名做实参.
一维数组名做实参,形参有三种写法: int *p , int p[10] , int p[ ]
//这三种写法只是形式不同,本质上都理解为指针int *p的形式
二维数组名做实参,形参有三种写法: int (*p)[4] , int p[2][4] , int p[ ][4]